home *** CD-ROM | disk | FTP | other *** search
/ Aminet 51 / Aminet 51 (2002)(GTI - Schatztruhe)[!][Oct 2002].iso / Aminet / util / misc / ReportPlus.lha / reportplus / source / f6.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-23  |  197.1 KB  |  4,896 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <intuition/intuition.h>
  4. #include <intuition/gadgetclass.h>
  5. #include <libraries/iffparse.h>
  6. #include <dos/dos.h>
  7. #include <dos/datetime.h>
  8.  
  9. #include <clib/alib_protos.h>
  10. #include <clib/exec_protos.h>
  11. #include <clib/intuition_protos.h>
  12. #include <clib/iffparse_protos.h>
  13. #include <clib/dos_protos.h>
  14.  
  15. #define ALL_REACTION_CLASSES
  16. #define ALL_REACTION_MACROS
  17. #include <reaction/reaction.h>
  18.  
  19. #include <ctype.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include "rp.h"
  23.  
  24. #define BYTESPERLINE 12 // how many bytes to print per line
  25.  
  26. #define ITEMS 255
  27. MODULE struct
  28. {   TEXT   name[5];
  29.     ULONG  bytes;
  30.     UBYTE* DataPtr;
  31. } contents[ITEMS + 1];
  32.  
  33. #define FORMS         89
  34.  
  35. #define CD             1
  36. #define OBSOLETE       2
  37. #define PRIVATE        4
  38. #define PROPOSAL       8
  39. #define RESERVED      16
  40. #define RKM           32
  41. #define STANDARD      64
  42. #define UNREGISTERED 128
  43.  
  44. #define IFFXCHARS     17
  45.  
  46. MODULE void iffquery(void);
  47. MODULE void PrintTopChunk(void);
  48. MODULE void readiff(void);
  49. MODULE void tellchunk(UWORD which);
  50. MODULE void chunkdesc(STRPTR desc, ABOOL isknown);
  51. MODULE void binarize(UBYTE data);
  52. MODULE void hexalize(UBYTE data);
  53. MODULE ULONG getulong(UBYTE* start);
  54. MODULE SLONG getslong(UBYTE* start);
  55. MODULE ULONG getuword(UBYTE* start);
  56. MODULE SLONG getsword(UBYTE* start);
  57. MODULE SLONG getsbyte(UBYTE* start);
  58. MODULE void writeiffgadgets(void);
  59. MODULE void dotextattr(UBYTE* offset);
  60. MODULE void docountry(UBYTE* offset);
  61. MODULE void tellchunk(UWORD which);
  62.  
  63. /* Text error messages for possible IFFERR_#? returns from various IFF
  64.  * routines. To get the index into this array, take your IFFERR code,
  65.  * negate it, and subtract one.
  66.  * idx = -error - 1;
  67.  */
  68. STRPTR errormsgs[] =
  69. {   "End of file (not an error).",
  70.     "End of context (not an error).",
  71.     "No lexical scope.",
  72.     "Insufficient memory.",
  73.     "Stream read error.",
  74.     "Stream write error.",
  75.     "Stream seek error.",
  76.     "File is corrupt.",
  77.     "IFF syntax error.",
  78.     "Not an IFF file.",
  79.     "Required call-back hook missing.",
  80.     "Return to client. You should never see this."
  81. };
  82.  
  83. // from rp.c
  84. IMPORT SBYTE              page;
  85. IMPORT struct Window*     MainWindowPtr;
  86. IMPORT struct TextAttr    Topaz8;
  87. IMPORT TEXT               aslresult[VLONGFIELD + 1],
  88.                           weekdaystring[LEN_DATSTRING],
  89.                           datestring[LEN_DATSTRING],
  90.                           timestring[LEN_DATSTRING],
  91.                           IOBuffer[LONGESTFIELD + 1];
  92. IMPORT Object*            WinObject[FUNCTIONS + 1]; // note that WindowObject is a reserved macro
  93. IMPORT struct Menu*       MenuPtr;
  94. IMPORT struct Screen*     ScreenPtr;
  95.  
  96. MODULE ABOOL             known, first;
  97. MODULE struct IFFHandle* IFFHandle             = NULL;
  98. MODULE struct List       List1,
  99.                          List2;
  100. MODULE TEXT  queryform[5] = "",
  101.              tempstring1[VLONGFIELD + 1],
  102.              tempstring2[13];
  103. MODULE ULONG items        = 0; // value of this is actual number of items allocated
  104. MODULE UWORD selectedform  = 0,
  105.              selectedchunk = 0;
  106. MODULE struct Gadget*    iff_gadgets[GIDS_6 + 1];
  107.     
  108. AGLOBAL struct IFFStruct iff;
  109.  
  110. MODULE struct
  111. {   UBYTE  flags;
  112.     TEXT   name[5];
  113.     STRPTR desc;
  114.     STRPTR contributor;
  115. } form[FORMS + 1] =
  116. {   STANDARD | RKM | CD,      "8SVX", "EA IFF 85 8-bit sound sample form",                    "EA/CBM",
  117.     RKM | CD,                 "AIFF", "Audio 1-32 bit samples",                               "Apple",
  118.     RKM | CD,                 "ACBM", "Amiga Contiguous Bitmap",                              "CBM",
  119.     UNREGISTERED,             "AHAM", "?",                                                    "?",
  120.     RKM | CD,                 "ANBM", "ANimated BitMap form",                                 "EA",
  121.     RKM | CD,                 "ANIM", "Cel ANIMation form",                                   "Sparta/Aegis",
  122.     PROPOSAL,                 "ARC ", "ARChive format",                                       "?",
  123.     UNREGISTERED,             "ARES", "?",                                                    "?",
  124.     RESERVED,                 "ATXT", "Temporarily reserved",                                 "?",
  125.     PRIVATE,                  "AVCF", "AmigaVision Flow",                                     "CBM",
  126.     NULL,                     "BANK", "Soundquest Editor/Librarian MIDI Sysex dump",          "?",
  127.     NULL,                     "BBSD", "BBS Database",                                         "Phalanx Software",
  128.     PRIVATE,                  "C100", "?",                                                    "Cloanto",
  129.     STANDARD,                 "CAT ", "EA IFF 85 group identifier",                           "EA/CBM",
  130.     PROPOSAL,                 "CELP", "Compressed ZyXEL voice data",                          "?",
  131.     RESERVED,                 "CHBM", "Chunky bitmap",                                        "Eric Lavitsky",
  132.     NULL,                     "CLIP", "CAT CLIP to hold various formats in clipboard",        "CBM",
  133.     PROPOSAL | CD,            "CMUS", "Common MUsical Score",                                 "Talin (David Joiner)",
  134.     NULL,                     "CPFM", "Cloanto Personal FontMaker",                           "Cloanto",
  135.     NULL,                     "DCCL", "DCTV paint clip",                                      "?",
  136.     NULL,                     "DCPA", "DCTV paint palette",                                   "?",
  137.     NULL,                     "DCTV", "DCTV raw picture file",                                "?",
  138.     PRIVATE,                  "DECK", "Inovatronics CanDo",                                   "Innovatronics",
  139.     CD,                       "DEEP", "Chunky pixel image files (used in TV Paint)",          "Amiga Centre Scotland",
  140.     RKM | CD,                 "DR2D", "2D object standard format",                            "Ross Cunniff & John Orr",
  141.     RESERVED,                 "DRAW", "?",                                                    "Jim Bayless",
  142.     CD,                       "DTYP", "DataTYPes identification",                             "Amiga, Inc.",
  143.     PROPOSAL | CD,            "EXEC", "Executable (loadseg-able) code",                       "Chris Ludwig",
  144.     RKM | CD,                 "FANT", "Fantavision movie format",                             "Broderbund",
  145.     OBSOLETE | PRIVATE,       "FAX3", "Facsimile image",                                      "GPSoftware",
  146.     CD,                       "FAXX", "Facsimile image",                                      "Atlantis Design Group",
  147.     RESERVED,                 "FIGR", "Deluxe Video",                                         "EA",
  148.     NULL,                     "FILM", "LIST FILM - stores ILBMs with interleaved 8SVX audio", "?",
  149.     RESERVED,                 "FNTR", "Raster font",                                          "EA",
  150.     RESERVED,                 "FNTV", "Vector font",                                          "EA",
  151.     STANDARD,                 "FORM", "Group identifier",                                     "EA/CBM",
  152.     STANDARD | RKM,           "FTXT", "Formatted TeXT",                                       "EA/CBM",
  153.     PROPOSAL | PRIVATE,       "GRYP", "Byteplane storage",                                    "?",
  154.     RESERVED,                 "GSCR", "General music SCoRe",                                  "EA",
  155.     PROPOSAL | PRIVATE,       "GUI ", "User interface storage",                               "?",
  156.     RKM | CD,                 "HEAD", "Flow idea processor",                                  "New Horizons Software",
  157.     STANDARD | RKM | CD,      "ILBM", "EA IFF 85 raster bitmap form",                         "EA/CBM",
  158.     RESERVED,                 "IOBJ", "?",                                                    "Seven Seas Software",
  159.     RESERVED,                 "IODK", "?",                                                    "Merging Technologies",
  160.     RESERVED,                 "ITRF", "?",                                                    "?",
  161.     RESERVED,                 "JMOV", "?",                                                    "Merging Technologies",
  162.     STANDARD,                 "LIST", "EA IFF 85 group identifier",                           "EA/CBM",
  163.     RESERVED,                 "MFAX", "Facsimile?",                                           "TKR GmbH & Co.",
  164.     NULL,                     "MIDI", "MIDI?",                                                "Circum Design",
  165.     PRIVATE,                  "MOVI", "LIST MOVIe?",                                          "?",
  166.     PRIVATE,                  "MSCX", "Music-X format",                                       "?",
  167.     RESERVED,                 "MSMP", "Temporarily reserved",                                 "?",
  168.     RKM | CD,                 "MTRX", "Numerical data storage (MathVision)",                  "Seven Seas Software",
  169.     NULL,                     "NSEQ", "Numerical sequence",                                   "Stockhausen GmbH",
  170.     PROPOSAL | CD,            "OB3D", "Standard 3D object",                                   "?",
  171.     RKM | CD,                 "PGTB", "ProGram TraceBack",                                    "SAS Institute",
  172.     RESERVED,                 "PICS", "Macintosh picture",                                    "EA",
  173.     RESERVED | OBSOLETE,      "PLBM", "?",                                                    "EA",
  174.     RESERVED | PROPOSAL | CD, "PMBC", "24-bit accurate images",                               "Black Belt Systems",
  175.     RESERVED | PRIVATE,       "PREF", "User preferences data",                                "CBM",
  176.     STANDARD,                 "PROP", "Group identifier",                                     "EA/CBM",
  177.     RKM | CD,                 "PRSP", "DPaint IV perspective move form",                      "EA",
  178.     NULL,                     "PTCH", "Patch file",                                           "SAS Institute",
  179.     RESERVED,                 "PTXT", "Temporarily reserved",                                 "?",
  180.     PRIVATE,                  "RGB4", "4-bit RGB",                                            "?",
  181.     RKM | CD,                 "RGB8", "RGB image (Turbo Silver)",                             "Impulse",
  182.     RKM | CD,                 "RGBN", "RGB image (Turbo Silver)",                             "Impulse",
  183.     RESERVED,                 "RGBX", "Temporarily reserved",                                 "?",
  184.     PRIVATE,                  "ROXN", "Animation",                                            "?",
  185.     RKM | CD,                 "SAMP", "SAMPled sound",                                        "Jim Fiore & Jeff Glatt",
  186.     PRIVATE,                  "SC3D", "SCene format (Sculpt-3D)",                             "?",
  187.     PRIVATE,                  "SHAK", "SHAKespeare format",                                   "?",
  188.     RESERVED | PRIVATE,       "SHO1", "?",                                                    "Gary Bonham",
  189.     RESERVED | PRIVATE,       "SHOW", "?",                                                    "Gary Bonham",
  190.     STANDARD | RKM,           "SMUS", "Simple MUsic Score",                                   "EA/CBM",
  191.     CD,                       "SPLT", "File SPLiTting system",                                "ASDG",
  192.     RESERVED,                 "SSRE", "?",                                                    "Merging Technologies",
  193.     UNREGISTERED,             "SWRT", "?",                                                    "?",
  194.     NULL,                     "SYTH", "SoundQuest Master Librarian MIDI System driver",       "?",
  195.     RESERVED,                 "TCDE", "?",                                                    "Merging Technologies",
  196.     RKM | CD,                 "TDDD", "3D rendering data (Turbo Silver)",                     "Impulse",
  197.     UNREGISTERED,             "TERM", "?",                                                    "?",
  198.     CD,                       "TMUI", "ToolMaker User Interface",                             "Michael Erwin",
  199.     CD,                       "TREE", "Arbitrary data structures as trees (or nested lists)", "Stefan Reisner",
  200.     CD | PROPOSAL,            "TRKR", "TRacKeR style music module",                           "Full Tilt Entertainment",
  201.     RESERVED,                 "USCR", "Uhuru SCoRe",                                          "EA",
  202.     RESERVED,                 "UVOX", "Uhuru Macintosh VOiXe",                                "EA",
  203.     PRIVATE,                  "VDEO", "Deluxe ViDEO",                                         "EA",
  204.     RKM | CD,                 "WORD", "ProWrite document",                                    "New Horizons Software",
  205.     CD,                       "YUVN", "For storage of Y:U:V image data",                      "MacroSystem"
  206. };
  207.  
  208. AGLOBAL void iff1(void)
  209. {   struct Hook Hook6Struct;
  210.     STRPTR      stringptr;
  211.  
  212.     InitHook(&Hook6Struct, Hook6Func, NULL);
  213.  
  214.     /* Create the window object. */
  215.     lockscreen();
  216.  
  217. if (!(WinObject[6] =
  218. NewObject
  219. (   WINDOW_GetClass(),                    NULL,
  220.     WA_PubScreen,                         ScreenPtr,
  221.     WA_ScreenTitle,                       "Report+",
  222.     WA_Title,                             "Report+: IFF FORM Viewer",
  223.     WA_Activate,                          TRUE,
  224.     WA_DepthGadget,                       TRUE,
  225.     WA_DragBar,                           TRUE,
  226.     WA_CloseGadget,                       TRUE,
  227.     WA_SizeGadget,                        TRUE,
  228.     WA_IDCMP,                             IDCMP_RAWKEY,
  229.     WINDOW_IDCMPHook,                     &Hook6Struct,
  230.     WINDOW_IDCMPHookBits,                 IDCMP_RAWKEY,
  231.     WINDOW_MenuStrip,                     MenuPtr,
  232.     WINDOW_Position,                      WPOS_CENTERSCREEN,
  233.     WINDOW_ParentGroup,                   iff_gadgets[GID_6_LY1] =
  234.     NewObject
  235.     (   LAYOUT_GetClass(),                NULL,
  236.         LAYOUT_Orientation,               LAYOUT_ORIENT_VERT,
  237.         LAYOUT_SpaceOuter,                TRUE,
  238.         LAYOUT_DeferLayout,               TRUE,
  239.         LAYOUT_AddChild,
  240.         NewObject
  241.         (   LAYOUT_GetClass(),            NULL,
  242.             LAYOUT_Orientation,           LAYOUT_ORIENT_HORIZ,
  243.             LAYOUT_SpaceOuter,            TRUE,
  244.             LAYOUT_DeferLayout,           TRUE,
  245.             LAYOUT_BevelStyle,            BVS_NONE,
  246.             LAYOUT_AddChild,
  247.             NewObject
  248.             (   LAYOUT_GetClass(),        NULL,
  249.                 LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
  250.                 LAYOUT_SpaceOuter,        TRUE,
  251.                 LAYOUT_VertAlignment,     LALIGN_CENTER,
  252.                 LAYOUT_BevelStyle,        BVS_NONE,
  253.                 LAYOUT_AddChild,
  254.                 NewObject
  255.                 (   LAYOUT_GetClass(),    NULL,
  256.                     LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
  257.                     LAYOUT_SpaceOuter,    TRUE,
  258.                     LAYOUT_HorizAlignment,LALIGN_RIGHT,
  259.                     LAYOUT_BevelStyle,    BVS_NONE,
  260.                     LAYOUT_AddImage,
  261.                     NewObject
  262.                     (   LABEL_GetClass(),     NULL,
  263.                         LABEL_Text,           "_FORM ID:",
  264.                         LABEL_Justification,  LJ_RIGHT,
  265.                     TAG_END),
  266.                 TAG_END),
  267.                 LAYOUT_AddChild,
  268.                 NewObject
  269.                 (   LAYOUT_GetClass(),        NULL,
  270.                     LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  271.                     LAYOUT_SpaceOuter,        TRUE,
  272.                     LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  273.                     LAYOUT_BevelStyle,        BVS_NONE,
  274.                     LAYOUT_AddImage,
  275.                     NewObject
  276.                     (   LABEL_GetClass(),     NULL,
  277.                         LABEL_Text,           "Description:",
  278.                         LABEL_Justification,  LJ_RIGHT,
  279.                     TAG_END),
  280.                 TAG_END),
  281.                 LAYOUT_AddChild,
  282.                 NewObject
  283.                 (   LAYOUT_GetClass(),        NULL,
  284.                     LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  285.                     LAYOUT_SpaceOuter,        TRUE,
  286.                     LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  287.                     LAYOUT_BevelStyle,        BVS_NONE,
  288.                     LAYOUT_AddImage,
  289.                     NewObject
  290.                     (   LABEL_GetClass(),     NULL,
  291.                         LABEL_Text,           "Contributor:",
  292.                         LABEL_Justification,  LJ_RIGHT,
  293.                     TAG_END),
  294.                 TAG_END),
  295.                 LAYOUT_AddChild,
  296.                 NewObject
  297.                 (   LAYOUT_GetClass(),        NULL,
  298.                     LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  299.                     LAYOUT_SpaceOuter,        TRUE,
  300.                     LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  301.                     LAYOUT_BevelStyle,        BVS_NONE,
  302.                     LAYOUT_AddImage,
  303.                     NewObject
  304.                     (   LABEL_GetClass(),     NULL,
  305.                         LABEL_Text,           "Chunk info:",
  306.                         LABEL_Justification,  LJ_RIGHT,
  307.                     TAG_END),
  308.                 TAG_END),
  309.                 LAYOUT_AddChild,
  310.                 NewObject
  311.                 (   LAYOUT_GetClass(),        NULL,
  312.                     LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  313.                     LAYOUT_SpaceOuter,        TRUE,
  314.                     LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  315.                     LAYOUT_BevelStyle,        BVS_NONE,
  316.                     LAYOUT_AddImage,
  317.                     NewObject
  318.                     (   LABEL_GetClass(),     NULL,
  319.                         LABEL_Text,           "_Pathname:",
  320.                         LABEL_Justification,  LJ_RIGHT,
  321.                     TAG_END),
  322.                 TAG_END),
  323.                 LAYOUT_AddChild,
  324.                 NewObject
  325.                 (   LAYOUT_GetClass(),        NULL,
  326.                     LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  327.                     LAYOUT_SpaceOuter,        TRUE,
  328.                     LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  329.                     LAYOUT_BevelStyle,        BVS_NONE,
  330.                     LAYOUT_AddImage,
  331.                     NewObject
  332.                     (   LABEL_GetClass(),     NULL,
  333.                         LABEL_Text,           "Status:",
  334.                         LABEL_Justification,  LJ_RIGHT,
  335.                     TAG_END),
  336.                 TAG_END),
  337.             TAG_END),
  338.             CHILD_WeightedWidth,      0,
  339.             LAYOUT_AddChild,
  340.             NewObject
  341.             (   LAYOUT_GetClass(),        NULL,
  342.                 LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
  343.                 LAYOUT_SpaceOuter,        TRUE,
  344.                 LAYOUT_VertAlignment,     LALIGN_CENTER,
  345.                 LAYOUT_HorizAlignment,    LALIGN_CENTER,
  346.                 LAYOUT_BevelStyle,        BVS_NONE,
  347.                 LAYOUT_AddChild,
  348.                 NewObject
  349.                 (   LAYOUT_GetClass(),    NULL,
  350.                     LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
  351.                     LAYOUT_SpaceOuter,    TRUE,
  352.                     LAYOUT_VertAlignment, LALIGN_CENTER,
  353.                     LAYOUT_HorizAlignment,LALIGN_LEFT,
  354.                     LAYOUT_BevelStyle,    BVS_NONE,
  355.                     LAYOUT_AddChild,          iff_gadgets[GID_6_ST1] =
  356.                     NewObject
  357.                     (   STRING_GetClass(),    NULL,
  358.                         GA_ID,                GID_6_ST1,
  359.                         GA_TabCycle,          TRUE,
  360.                         GA_RelVerify,         TRUE,
  361.                         STRINGA_TextVal,      queryform,
  362.                         STRINGA_ReplaceMode,  TRUE,
  363.                         STRINGA_MinVisible,   4,
  364.                         STRINGA_MaxChars,     4 + 1,
  365.                     TAG_END),
  366.                     CHILD_WeightedWidth,      50,
  367.                     LAYOUT_AddChild,          iff_gadgets[GID_6_CB1] =
  368.                     NewObject
  369.                     (   CHECKBOX_GetClass(),  NULL,
  370.                         GA_ID,                GID_6_CB1,
  371.                         GA_RelVerify,         TRUE,
  372.                         GA_Text,              "_Raw view only?",
  373.                         GA_Selected,          (BOOL) iff.raw,
  374.                     TAG_END),
  375.                     CHILD_WeightedWidth,      50,
  376.                 TAG_END),    
  377.                 LAYOUT_AddChild,          iff_gadgets[GID_6_ST2] =
  378.                 NewObject
  379.                 (   STRING_GetClass(),    NULL,
  380.                     GA_ID,                GID_6_ST2,
  381.                     GA_ReadOnly,          TRUE,
  382.                     STRINGA_TextVal,      "-",
  383.                     STRINGA_MinVisible,   20,
  384.                 TAG_END),
  385.                 LAYOUT_AddChild,          iff_gadgets[GID_6_ST3] =
  386.                 NewObject
  387.                 (   STRING_GetClass(),    NULL,
  388.                     GA_ID,                GID_6_ST3,
  389.                     GA_ReadOnly,          TRUE,
  390.                     STRINGA_TextVal,      "-",
  391.                     STRINGA_MinVisible,   20,
  392.                 TAG_END),
  393.                 LAYOUT_AddChild,          iff_gadgets[GID_6_ST4] =
  394.                 NewObject
  395.                 (   STRING_GetClass(),    NULL,
  396.                     GA_ID,                GID_6_ST4,
  397.                     GA_ReadOnly,          TRUE,
  398.                     STRINGA_TextVal,      "-",
  399.                     STRINGA_MinVisible,   20,
  400.                 TAG_END),
  401.                 LAYOUT_AddChild,
  402.                 NewObject
  403.                 (   LAYOUT_GetClass(),    NULL,
  404.                     LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
  405.                     LAYOUT_SpaceOuter,    TRUE,
  406.                     LAYOUT_VertAlignment, LALIGN_CENTER,
  407.                     LAYOUT_HorizAlignment,LALIGN_LEFT,
  408.                     LAYOUT_BevelStyle,    BVS_NONE,
  409.                     LAYOUT_AddChild,          iff_gadgets[GID_6_ST6] =
  410.                     NewObject
  411.                     (   STRING_GetClass(),    NULL,
  412.                         GA_ID,                GID_6_ST6,
  413.                         GA_RelVerify,         TRUE,
  414.                         GA_TabCycle,          TRUE,
  415.                         STRINGA_TextVal,      iff.pathname,
  416.                         STRINGA_MinVisible,   20,
  417.                         STRINGA_MaxChars,     PATHNAMEFIELD,
  418.                     TAG_END),
  419.                     LAYOUT_AddChild,      iff_gadgets[GID_6_BU1] =
  420.                     NewObject
  421.                     (   NULL,             "button.gadget",
  422.                         GA_ID,            GID_6_BU1,
  423.                         GA_RelVerify,     TRUE,
  424.                         BUTTON_AutoButton,BAG_POPFILE,
  425.                     TAG_END),
  426.                     CHILD_WeightedWidth,  0,
  427.                 TAG_END),
  428.                 CHILD_WeightedHeight,     0,
  429.                 LAYOUT_AddChild,          iff_gadgets[GID_6_ST5] =
  430.                 NewObject
  431.                 (   STRING_GetClass(),    NULL,
  432.                     GA_ID,                GID_6_ST5,
  433.                     GA_ReadOnly,          TRUE,
  434.                     STRINGA_TextVal,      "Ready.",
  435.                     STRINGA_MinVisible,   20,
  436.                 TAG_END),
  437.             TAG_END),
  438.         TAG_END),
  439.         CHILD_WeightedHeight,         0,
  440.         LAYOUT_AddChild,
  441.         NewObject
  442.         (   LAYOUT_GetClass(),        NULL,
  443.             LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  444.             LAYOUT_SpaceOuter,        TRUE,
  445.             LAYOUT_HorizAlignment,    LALIGN_CENTER,
  446.             LAYOUT_BevelStyle,        BVS_NONE,
  447.             LAYOUT_AddChild,
  448.             NewObject
  449.             (   LAYOUT_GetClass(),        NULL,
  450.                 LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
  451.                 LAYOUT_SpaceOuter,        TRUE,
  452.                 LAYOUT_HorizAlignment,    LALIGN_CENTER,
  453.                 LAYOUT_BevelStyle,        BVS_NONE,
  454.                 LAYOUT_AddImage,
  455.                 NewObject
  456.                 (   LABEL_GetClass(),     NULL,
  457.                     LABEL_Text,           "Chunks:",
  458.                     LABEL_Justification,  LJ_CENTER,
  459.                 TAG_END),
  460.                 CHILD_WeightedHeight,     0,
  461.                 LAYOUT_AddChild,          iff_gadgets[GID_6_LB1] =
  462.                 NewObject
  463.                 (   LISTBROWSER_GetClass(),NULL,
  464.                     GA_ID,                 GID_6_LB1,
  465.                     GA_RelVerify,          TRUE,
  466.                     GA_TextAttr,           &Topaz8,
  467.                     LISTBROWSER_Labels,    (ULONG) &List1,
  468.                 TAG_END),
  469.             TAG_END),
  470.             CHILD_WeightedWidth,           25,
  471.             CHILD_MinWidth,               172,
  472.             LAYOUT_AddChild,
  473.             NewObject
  474.             (   LAYOUT_GetClass(),        NULL,
  475.                 LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
  476.                 LAYOUT_SpaceOuter,        TRUE,
  477.                 LAYOUT_HorizAlignment,    LALIGN_CENTER,
  478.                 LAYOUT_BevelStyle,        BVS_NONE,
  479.                 LAYOUT_AddImage,
  480.                 NewObject
  481.                 (   LABEL_GetClass(),     NULL,
  482.                     LABEL_Text,           "Chunk contents:",
  483.                     LABEL_Justification,  LJ_CENTER,
  484.                 TAG_END),
  485.                 CHILD_WeightedHeight,     0,
  486.                 LAYOUT_AddChild,          iff_gadgets[GID_6_LB2] =
  487.                 NewObject
  488.                 (   LISTBROWSER_GetClass(),NULL,
  489.                     GA_ID,                 GID_6_LB2,
  490.                     GA_RelVerify,          TRUE,
  491.                     GA_TextAttr,           &Topaz8,
  492.                     LISTBROWSER_Labels,    (ULONG) &List2,
  493.                 TAG_END),
  494.             TAG_END),
  495.         TAG_END),
  496.         CHILD_WeightedHeight,          100,
  497.         CHILD_MinHeight,               128,
  498.         LAYOUT_AddChild,
  499.         NewObject
  500.         (   LAYOUT_GetClass(),        NULL,
  501.             LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  502.             LAYOUT_SpaceOuter,        TRUE,
  503.             LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  504.             LAYOUT_BevelStyle,        BVS_FIELD,
  505.             LAYOUT_AddChild,
  506.             NewObject
  507.             (   LAYOUT_GetClass(),        NULL,
  508.                 LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
  509.                 LAYOUT_SpaceOuter,        TRUE,
  510.                 LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  511.                 LAYOUT_BevelStyle,        BVS_NONE,
  512.                 LAYOUT_AddImage,
  513.                 NewObject
  514.                 (   LABEL_GetClass(),     NULL,
  515.                     LABEL_Text,           "",
  516.                 TAG_END),
  517.                 CHILD_WeightedHeight,     50,
  518.                 LAYOUT_AddImage,
  519.                 NewObject
  520.                 (   LABEL_GetClass(),     NULL,
  521.                     LABEL_Text,           "Status:",
  522.                     LABEL_Justification,  LJ_RIGHT,
  523.                 TAG_END),
  524.                 CHILD_WeightedHeight,     0,
  525.                 LAYOUT_AddImage,
  526.                 NewObject
  527.                 (   LABEL_GetClass(),     NULL,
  528.                     LABEL_Text,           "",
  529.                 TAG_END),
  530.                 CHILD_WeightedHeight,     50,
  531.             TAG_END),
  532.             CHILD_WeightedWidth,          20,
  533.             LAYOUT_AddChild,
  534.             NewObject
  535.             (   LAYOUT_GetClass(),        NULL,
  536.                 LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  537.                 LAYOUT_SpaceOuter,        TRUE,
  538.                 LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  539.                 LAYOUT_BevelStyle,        BVS_NONE,
  540.                 LAYOUT_AddChild,
  541.                 NewObject
  542.                 (   LAYOUT_GetClass(),        NULL,
  543.                     LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
  544.                     LAYOUT_SpaceOuter,        TRUE,
  545.                     LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  546.                     LAYOUT_BevelStyle,        BVS_NONE,
  547.                     LAYOUT_AddChild,
  548.                     NewObject
  549.                     (   LAYOUT_GetClass(),        NULL,
  550.                         LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  551.                         LAYOUT_SpaceOuter,        TRUE,
  552.                         LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  553.                         LAYOUT_BevelStyle,        BVS_NONE,
  554.                         LAYOUT_AddChild,          iff_gadgets[GID_6_CB2] =
  555.                         NewObject
  556.                         (   CHECKBOX_GetClass(),  NULL,
  557.                             GA_ID,                GID_6_CB2,
  558.                             GA_Disabled,          TRUE,
  559.                             GA_Text,              "Obsolete?",
  560.                             GA_Selected,          (BOOL) iff.obsolete,
  561.                         TAG_END),
  562.                         CHILD_WeightedWidth,      33,
  563.                         LAYOUT_AddChild,          iff_gadgets[GID_6_CB3] =
  564.                         NewObject
  565.                         (   CHECKBOX_GetClass(),  NULL,
  566.                             GA_ID,                GID_6_CB3,
  567.                             GA_Disabled,          TRUE,
  568.                             GA_Text,              "Private?",
  569.                             GA_Selected,          (BOOL) iff.private,
  570.                         TAG_END),
  571.                         CHILD_WeightedWidth,      33,
  572.                         LAYOUT_AddChild,          iff_gadgets[GID_6_CB4] =
  573.                         NewObject
  574.                         (   CHECKBOX_GetClass(),  NULL,
  575.                             GA_ID,                GID_6_CB4,
  576.                             GA_Disabled,          TRUE,
  577.                             GA_Text,              "Proposal?",
  578.                             GA_Selected,          (BOOL) iff.proposal,
  579.                         TAG_END),
  580.                         CHILD_WeightedWidth,      34,
  581.                     TAG_END),
  582.                     LAYOUT_AddChild,
  583.                     NewObject
  584.                     (   LAYOUT_GetClass(),        NULL,
  585.                         LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  586.                         LAYOUT_SpaceOuter,        TRUE,
  587.                         LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  588.                         LAYOUT_BevelStyle,        BVS_NONE,
  589.                         LAYOUT_AddChild,          iff_gadgets[GID_6_CB5] =
  590.                         NewObject
  591.                         (   CHECKBOX_GetClass(),  NULL,
  592.                             GA_ID,                GID_6_CB5,
  593.                             GA_Disabled,          TRUE,
  594.                             GA_Text,              "Reserved?",
  595.                             GA_Selected,          (BOOL) iff.reserved,
  596.                         TAG_END),
  597.                         CHILD_WeightedWidth,      33,
  598.                         LAYOUT_AddChild,          iff_gadgets[GID_6_CB6] =
  599.                         NewObject
  600.                         (   CHECKBOX_GetClass(),  NULL,
  601.                             GA_ID,                GID_6_CB6,
  602.                             GA_Disabled,          TRUE,
  603.                             GA_Text,              "Standard?",
  604.                             GA_Selected,          (BOOL) iff.standard,
  605.                         TAG_END),
  606.                         CHILD_WeightedWidth,      33,
  607.                         LAYOUT_AddChild,          iff_gadgets[GID_6_CB7] =
  608.                         NewObject
  609.                         (   CHECKBOX_GetClass(),  NULL,
  610.                             GA_ID,                GID_6_CB7,
  611.                             GA_Disabled,          TRUE,
  612.                             GA_Text,              "Unregistered?",
  613.                             GA_Selected,          (BOOL) iff.unregistered,
  614.                         TAG_END),
  615.                         CHILD_WeightedWidth,      34,
  616.                     TAG_END),
  617.                 TAG_END),
  618.             TAG_END),
  619.             CHILD_WeightedWidth,                  80,
  620.         TAG_END),
  621.         CHILD_WeightedHeight,         0,
  622.         LAYOUT_AddChild,
  623.         NewObject
  624.         (   LAYOUT_GetClass(),        NULL,
  625.             LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  626.             LAYOUT_SpaceOuter,        TRUE,
  627.             LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  628.             LAYOUT_BevelStyle,        BVS_FIELD,
  629.             LAYOUT_AddChild,
  630.             NewObject
  631.             (   LAYOUT_GetClass(),        NULL,
  632.                 LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
  633.                 LAYOUT_SpaceOuter,        TRUE,
  634.                 LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  635.                 LAYOUT_VertAlignment,     LALIGN_CENTER,
  636.                 LAYOUT_BevelStyle,        BVS_NONE,
  637.                 LAYOUT_AddChild,
  638.                 NewObject
  639.                 (   LAYOUT_GetClass(),        NULL,
  640.                     LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  641.                     LAYOUT_SpaceOuter,        TRUE,
  642.                     LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  643.                     LAYOUT_VertAlignment,     LALIGN_CENTER,
  644.                     LAYOUT_BevelStyle,        BVS_NONE,
  645.                     LAYOUT_AddImage,
  646.                     NewObject
  647.                     (   LABEL_GetClass(),     NULL,
  648.                         LABEL_Text,           "Documents:",
  649.                         LABEL_Justification,  LJ_RIGHT,
  650.                     TAG_END),
  651.                     CHILD_WeightedHeight,     0,
  652.                 TAG_END),
  653.             TAG_END),
  654.             CHILD_WeightedWidth,          20,
  655.             LAYOUT_AddChild,
  656.             NewObject
  657.             (   LAYOUT_GetClass(),        NULL,
  658.                 LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  659.                 LAYOUT_SpaceOuter,        TRUE,
  660.                 LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  661.                 LAYOUT_BevelStyle,        BVS_NONE,
  662.                 LAYOUT_AddChild,
  663.                 NewObject
  664.                 (   LAYOUT_GetClass(),        NULL,
  665.                     LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  666.                     LAYOUT_SpaceOuter,        TRUE,
  667.                     LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  668.                     LAYOUT_BevelStyle,        BVS_NONE,
  669.                     LAYOUT_AddChild,
  670.                     NewObject
  671.                     (   LAYOUT_GetClass(),        NULL,
  672.                         LAYOUT_Orientation,       LAYOUT_ORIENT_HORIZ,
  673.                         LAYOUT_SpaceOuter,        TRUE,
  674.                         LAYOUT_HorizAlignment,    LALIGN_RIGHT,
  675.                         LAYOUT_BevelStyle,        BVS_NONE,
  676.                         LAYOUT_AddChild,          iff_gadgets[GID_6_CB8] =
  677.                         NewObject
  678.                         (   CHECKBOX_GetClass(),  NULL,
  679.                             GA_ID,                GID_6_CB8,
  680.                             GA_Disabled,          TRUE,
  681.                             GA_Text,              "RKM?",
  682.                             GA_Selected,          (BOOL) iff.rkm,
  683.                         TAG_END),
  684.                         CHILD_WeightedWidth,      33,
  685.                         LAYOUT_AddChild,          iff_gadgets[GID_6_CB9] =
  686.                         NewObject
  687.                         (   CHECKBOX_GetClass(),  NULL,
  688.                             GA_ID,                GID_6_CB9,
  689.                             GA_Disabled,          TRUE,
  690.                             GA_Text,              "ADCD 2.1?",
  691.                             GA_Selected,          (BOOL) iff.cd,
  692.                         TAG_END),
  693.                         CHILD_WeightedWidth,       33,
  694.                         LAYOUT_AddImage,           NewObject
  695.                         (   LABEL_GetClass(),      NULL,
  696.                             LABEL_Text,            "",
  697.                         TAG_END),
  698.                         CHILD_WeightedWidth,       34,
  699.                     TAG_END),
  700.                 TAG_END),
  701.             TAG_END),
  702.             CHILD_WeightedWidth,           80,
  703.         TAG_END),
  704.         CHILD_WeightedHeight,              0,
  705.     TAG_END),
  706. TAG_END)))
  707. {   rq("Can't create ReAction gadgets!");
  708. }
  709. unlockscreen();
  710. openwindow();
  711.  
  712.     if (iff.pathname[0])
  713.     {   readiff();
  714.     } elif (queryform[0])
  715.     {   iffquery();
  716.     }
  717.  
  718.     ActivateLayoutGadget(iff_gadgets[GID_6_LY1], MainWindowPtr, NULL, (Object) iff_gadgets[GID_6_ST6]);
  719.  
  720.     loop();
  721.  
  722.     if (!(GetAttr
  723.     (   STRINGA_TextVal, iff_gadgets[GID_6_ST1], (ULONG *) &stringptr
  724.     )))
  725.     {   rq("Unsupported inquiry!"); // should never happen
  726.     }
  727.     strcpy(queryform, stringptr);
  728.  
  729.     if (!(GetAttr
  730.     (   STRINGA_TextVal, iff_gadgets[GID_6_ST6], (ULONG *) &stringptr
  731.     )))
  732.     {   rq("Unsupported inquiry!"); // should never happen
  733.     }
  734.     strcpy(iff.pathname, stringptr);
  735.  
  736.     closewindow();
  737.     // now that the window is closed we can free lists
  738.     iff_exit();
  739. }
  740.  
  741. AGLOBAL void iff_loop(ULONG gid)
  742. {   STRPTR stringptr;
  743.     ULONG  code;
  744.  
  745.     switch(gid)
  746.     {
  747.     case GID_6_CB1:
  748.         if (!(GetAttr
  749.         (   GA_Selected, iff_gadgets[GID_6_CB1], (ULONG *) &iff.raw
  750.         )))
  751.         {   rq("Unsupported inquiry!"); // should never happen
  752.         }
  753.         if (selectedchunk && known)
  754.         {   tellchunk(selectedchunk);
  755.         }
  756.     break;
  757.     case GID_6_ST1:
  758.         if (!(GetAttr
  759.         (   STRINGA_TextVal, iff_gadgets[GID_6_ST1], (ULONG *) &stringptr
  760.         )))
  761.         {   rq("Unsupported inquiry!"); // should never happen
  762.         }
  763.         strcpy(queryform, stringptr);
  764.  
  765.         iff.pathname[0] = 0;
  766.         SetGadgetAttrs
  767.         (   iff_gadgets[GID_6_ST6],
  768.             MainWindowPtr, NULL,
  769.             STRINGA_TextVal, iff.pathname,
  770.             TAG_END
  771.         );
  772.         SetGadgetAttrs
  773.         (   iff_gadgets[GID_6_ST5],
  774.             MainWindowPtr, NULL,
  775.             STRINGA_TextVal, "Ready.",
  776.             TAG_END
  777.         );
  778.         iffquery();
  779.     break;
  780.     case GID_6_ST6:
  781.         if (!(GetAttr
  782.         (   STRINGA_TextVal, iff_gadgets[GID_6_ST6], (ULONG *) &stringptr
  783.         )))
  784.         {   rq("Unsupported inquiry!"); // should never happen
  785.         }
  786.         strcpy(iff.pathname, stringptr);
  787.         readiff();
  788.     break;
  789.     case GID_6_BU1:
  790.         if (asl("~(#?.info)"))
  791.         {   strcpy(iff.pathname, aslresult);
  792.             SetGadgetAttrs
  793.             (   iff_gadgets[GID_6_ST6],
  794.                 MainWindowPtr, NULL,
  795.                 STRINGA_TextVal, iff.pathname,
  796.                 TAG_END
  797.             );
  798.             readiff();
  799.         }
  800.     break;
  801.     case GID_6_LB1:
  802.         /* code is the position within the list, starting from 0. */
  803.  
  804.         if (!(GetAttr
  805.         (   LISTBROWSER_Selected, iff_gadgets[GID_6_LB1], (ULONG *) &code
  806.         )))
  807.         {   rq("Unsupported inquiry!"); // should never happen
  808.         }
  809.         selectedchunk = code + 1;
  810.         tellchunk(selectedchunk);
  811.     break;
  812.     default:
  813.     break;
  814. }   }
  815.  
  816. MODULE void iffquery(void)
  817. {   ULONG i;
  818.  
  819.     /* Make any corrections to input now, to make it
  820.     easier to search the database. */
  821.     for (i = 0; i <= 3; i++)
  822.         if (queryform[i] >= 97 && queryform[i] <= 122)
  823.             queryform[i] -= 32;
  824.         elif (queryform[i] == 0)
  825.             queryform[i] = ' ';
  826.     queryform[4] = 0;
  827.  
  828.     SetGadgetAttrs
  829.     (   iff_gadgets[GID_6_ST1],
  830.         MainWindowPtr, NULL,
  831.         STRINGA_TextVal, queryform,
  832.         TAG_END
  833.     );
  834.  
  835.     selectedform = (UWORD) -1;
  836.     for (i = 0; i <= FORMS; i++)
  837.     if
  838.     (   queryform[0] == form[i].name[0]
  839.      && queryform[1] == form[i].name[1]
  840.      && queryform[2] == form[i].name[2]
  841.      && queryform[3] == form[i].name[3]
  842.     )
  843.     {   selectedform = i;
  844.         break;
  845.     }
  846.     selectedchunk = 0;
  847.     if (selectedform == (UWORD) -1)
  848.     {   iff.cd           =
  849.         iff.rkm          =
  850.         iff.private      =
  851.         iff.proposal     =
  852.         iff.obsolete     =
  853.         iff.reserved     =
  854.         iff.standard     =
  855.         iff.unregistered = FALSE;
  856.  
  857.         SetGadgetAttrs
  858.         (   iff_gadgets[GID_6_ST2],
  859.             MainWindowPtr, NULL,
  860.             STRINGA_TextVal, "-",
  861.             TAG_END
  862.         );
  863.         SetGadgetAttrs
  864.         (   iff_gadgets[GID_6_ST3],
  865.             MainWindowPtr, NULL,
  866.             STRINGA_TextVal, "-",
  867.             TAG_END
  868.         );
  869.     } else
  870.     {   iff.cd           = form[selectedform].flags & CD;
  871.         iff.rkm          = form[selectedform].flags & RKM;
  872.         iff.private      = form[selectedform].flags & PRIVATE;
  873.         iff.proposal     = form[selectedform].flags & PROPOSAL;
  874.         iff.obsolete     = form[selectedform].flags & OBSOLETE;
  875.         iff.reserved     = form[selectedform].flags & RESERVED;
  876.         iff.standard     = form[selectedform].flags & STANDARD;
  877.         iff.unregistered = form[selectedform].flags & UNREGISTERED;
  878.  
  879.         SetGadgetAttrs
  880.         (   iff_gadgets[GID_6_ST2],
  881.             MainWindowPtr, NULL,
  882.             STRINGA_TextVal, form[selectedform].desc,
  883.             TAG_END
  884.         );
  885.         SetGadgetAttrs
  886.         (   iff_gadgets[GID_6_ST3],
  887.             MainWindowPtr, NULL,
  888.             STRINGA_TextVal, form[selectedform].contributor,
  889.             TAG_END
  890.         );
  891.     }
  892.  
  893.     writeiffgadgets();
  894.  
  895.     SetGadgetAttrs
  896.     (   iff_gadgets[GID_6_LB1],
  897.         MainWindowPtr, NULL,
  898.         LISTBROWSER_Labels, NULL, // detach it
  899.         TAG_END
  900.     );
  901.     clearreactionlist(&List1);
  902.  
  903.     SetGadgetAttrs
  904.     (   iff_gadgets[GID_6_LB2],
  905.         MainWindowPtr, NULL,
  906.         LISTBROWSER_Labels, NULL, // detach it
  907.         TAG_END
  908.     );
  909.     clearreactionlist(&List2);
  910.  
  911.     for (i = 0; i < items; i++)
  912.     {   if (contents[i].DataPtr)
  913.         {   FreeMem(contents[i].DataPtr, contents[i].bytes);
  914.             contents[i].DataPtr = NULL;
  915.     }   }
  916.     items = 0;
  917. }
  918.  
  919. MODULE void readiff(void)
  920. {   LONG error;
  921.  
  922.     iffquery();
  923.  
  924.     /* Allocate IFF_File structure. */
  925.     if (!(IFFHandle = AllocIFF()))
  926.     {   DisplayBeep(NULL);
  927.         SetGadgetAttrs
  928.         (   iff_gadgets[GID_6_ST5],
  929.             MainWindowPtr, NULL,
  930.             STRINGA_TextVal, "AllocIFF() failed!",
  931.             TAG_END
  932.         );
  933.  
  934.         goto bye;
  935.     }
  936.  
  937.     first = TRUE;
  938.  
  939.     /* Set up IFF_File for AmigaDOS I/O.  */
  940.     if (!(IFFHandle->iff_Stream = Open(iff.pathname, MODE_OLDFILE)))
  941.     {   DisplayBeep(NULL);
  942.         SetGadgetAttrs
  943.         (   iff_gadgets[GID_6_ST5],
  944.             MainWindowPtr, NULL,
  945.             STRINGA_TextVal, "Can't open file!",
  946.             TAG_END
  947.         );
  948.         SetGadgetAttrs
  949.         (   iff_gadgets[GID_6_ST2],
  950.             MainWindowPtr, NULL,
  951.             STRINGA_TextVal, "-",
  952.             TAG_END
  953.         );
  954.         SetGadgetAttrs
  955.         (   iff_gadgets[GID_6_ST3],
  956.             MainWindowPtr, NULL,
  957.             STRINGA_TextVal, "-",
  958.             TAG_END
  959.         );
  960.  
  961.         queryform[0]     = 0;
  962.         iff.obsolete     =
  963.         iff.private      =
  964.         iff.proposal     =
  965.         iff.reserved     =
  966.         iff.standard     =
  967.         iff.unregistered =
  968.         iff.rkm          =
  969.         iff.cd           = FALSE;
  970.         writeiffgadgets();
  971.         goto bye;
  972.     }
  973.     InitIFFasDOS(IFFHandle);
  974.  
  975.     /* Start the IFF transaction. */
  976.     if (error = OpenIFF(IFFHandle, IFFF_READ))
  977.     {   DisplayBeep(NULL);
  978.         SetGadgetAttrs
  979.         (   iff_gadgets[GID_6_ST5],
  980.             MainWindowPtr, NULL,
  981.             STRINGA_TextVal, "OpenIFF() failed!",
  982.             TAG_END
  983.         );
  984.         goto bye;
  985.     }
  986.  
  987.     while (1)
  988.     {   /* IFFPARSE_RAWSTEP permits us to have precision monitoring of the
  989.          * parsing process, which is necessary if we wish to print the
  990.          * structure of an IFF file.
  991.          *   ParseIFF() with _RAWSTEP will return the following things for
  992.          * the following reasons:
  993.          *
  994.          * Return code:                 Reason:
  995.          * 0                            Entered new context.
  996.          * IFFERR_EOC                   About to leave a context.
  997.          * IFFERR_EOF                   Encountered end-of-file.
  998.          * <anything else>              A parsing error.
  999.          */
  1000.         error = ParseIFF(IFFHandle, IFFPARSE_RAWSTEP);
  1001.  
  1002.         /*
  1003.          * Since we're only interested in when we enter a context, we
  1004.          * "discard" end-of-context (_EOC) events.
  1005.          */
  1006.         if (error == IFFERR_EOC)
  1007.             continue;
  1008.         elif (error)
  1009.         {   // Leave the loop if there is any other error.
  1010.             break;
  1011.         }
  1012.  
  1013.         /* If we get here, error was zero. Print out the current state of
  1014.          * affairs. */
  1015.         PrintTopChunk();
  1016.     }
  1017.  
  1018.     /* If error was IFFERR_EOF, then the parser encountered the end of
  1019.      * the file without problems. Otherwise, we print a diagnostic.
  1020.      */
  1021.     if (error == IFFERR_EOF)
  1022.     {   SetGadgetAttrs
  1023.         (   iff_gadgets[GID_6_ST5],
  1024.             MainWindowPtr, NULL,
  1025.             STRINGA_TextVal, "Ready.",
  1026.             TAG_END
  1027.         );
  1028.         SetGadgetAttrs
  1029.         (   iff_gadgets[GID_6_LB1],
  1030.             MainWindowPtr, NULL,
  1031.             LISTBROWSER_Labels, &List1,
  1032.             TAG_END
  1033.         );
  1034.     } else
  1035.     {   SetGadgetAttrs
  1036.         (   iff_gadgets[GID_6_ST5],
  1037.             MainWindowPtr, NULL,
  1038.             STRINGA_TextVal, errormsgs[-error - 1],
  1039.             TAG_END
  1040.         );
  1041.         SetGadgetAttrs
  1042.         (   iff_gadgets[GID_6_LB1],
  1043.             MainWindowPtr, NULL,
  1044.             LISTBROWSER_Labels, NULL, // detach it
  1045.             TAG_END
  1046.         );
  1047.     }
  1048.  
  1049. bye:
  1050.     if (IFFHandle)
  1051.     {   /* Terminate the IFF transaction with the stream. Free all
  1052.          * associated structures. */
  1053.         CloseIFF(IFFHandle);
  1054.         // Close the stream itself.
  1055.         if (IFFHandle->iff_Stream)
  1056.         {   Close(IFFHandle->iff_Stream);
  1057.         }
  1058.         // Free the IFF_File structure itself.
  1059.         FreeIFF(IFFHandle);
  1060.         IFFHandle = NULL;
  1061. }   }
  1062.  
  1063. AGLOBAL void iff_exit(void)
  1064. {   ULONG i;
  1065.  
  1066.     if (IFFHandle)
  1067.     {   /* Terminate the IFF transaction with the stream. Free all
  1068.          * associated structures. */
  1069.         CloseIFF(IFFHandle);
  1070.         // Close the stream itself.
  1071.         if (IFFHandle->iff_Stream)
  1072.         {   Close(IFFHandle->iff_Stream);
  1073.         }
  1074.         // Free the IFF_File structure itself.
  1075.         FreeIFF(IFFHandle);
  1076.         IFFHandle = NULL;
  1077.     }
  1078.  
  1079.     clearreactionlist(&List2);
  1080.     clearreactionlist(&List1);
  1081.  
  1082.     for (i = 0; i < items; i++)
  1083.     {   if (contents[i].DataPtr)
  1084.         {   FreeMem(contents[i].DataPtr, contents[i].bytes);
  1085.             contents[i].DataPtr = NULL;
  1086.     }   }
  1087.     items = 0;
  1088. }
  1089.  
  1090. MODULE void PrintTopChunk(void)
  1091. {   struct ContextNode* top;
  1092.     short               i;
  1093.     char                idbuf[5];
  1094.     ULONG               length;
  1095.  
  1096.     /* Get a pointer to the context node describing the current context. */
  1097.     if (!(top = CurrentChunk(IFFHandle)))
  1098.         return;
  1099.  
  1100.     /* Print spaces equivalent to the current nesting depth of chunks
  1101.      * processed so far.
  1102.      *   This will cause nested chunks to be printed out indented. */
  1103.  
  1104.     tempstring1[0] = 0;
  1105.     if (IFFHandle->iff_Depth > 2)
  1106.     {   for (i = IFFHandle->iff_Depth - 2; i--; )
  1107.            strcat(tempstring1, " ");
  1108.     }
  1109.     strcpy(contents[items].name, IDtoStr(top->cn_ID, idbuf));
  1110.     contents[items].DataPtr = NULL;
  1111.  
  1112.     /* Print out the current chunk's ID and size. */
  1113.     strcat(tempstring1, IDtoStr(top->cn_ID, idbuf));
  1114.     stcl_d(tempstring2, top->cn_Size);
  1115.  
  1116.     length = IFFXCHARS - strlen(tempstring1) - strlen(tempstring2);
  1117.     for (i = 1; i <= length; i++)
  1118.     {   strcat(tempstring1, " ");
  1119.     }
  1120.     strcat(tempstring1, tempstring2);
  1121.  
  1122.     /* Print the current chunk's type, with a newline. */
  1123.     addreactionnode(&List1, tempstring1);
  1124.  
  1125.     if (!strcmp(IDtoStr(top->cn_ID, idbuf), "FORM"))
  1126.     {   if (first)
  1127.         {   first = FALSE;
  1128.             strcpy(queryform, IDtoStr(top->cn_Type, idbuf));
  1129.             iffquery();
  1130.     }   }
  1131.     else
  1132.     {   contents[items].bytes = top->cn_Size;
  1133.         if (!(contents[items].DataPtr = AllocMem(contents[items].bytes, MEMF_CLEAR)))
  1134.         {   rq("Out of memory!");
  1135.         }
  1136.         if (ReadChunkBytes(IFFHandle, contents[items].DataPtr, contents[items].bytes) < 0)
  1137.         {   rq("ReadChunkBytes() failed!");
  1138.     }   }
  1139.  
  1140.     items++;
  1141.     if (items > ITEMS)
  1142.     {   rq("Too many chunks!");
  1143. }   }
  1144.  
  1145. MODULE void tellchunk(UWORD which)
  1146. {   SLONG           svalue;
  1147.     ULONG           i, j, uvalue, length, markers, currentpos;
  1148.     struct DateTime DateTime;
  1149.  
  1150.     if (which == (UWORD) ~0)
  1151.     {   return;
  1152.     }
  1153.  
  1154.     SetGadgetAttrs
  1155.     (   iff_gadgets[GID_6_LB2],
  1156.         MainWindowPtr, NULL,
  1157.         LISTBROWSER_Labels, NULL, // detach it
  1158.         TAG_END
  1159.     );
  1160.     clearreactionlist(&List2);
  1161.     known = FALSE;
  1162.  
  1163.     if (!stricmp(contents[which].name, "FORM"))
  1164.     {   chunkdesc("-", TRUE);
  1165.     } elif (!stricmp(contents[which].name, "(c) "))
  1166.     {   chunkdesc("© Copyright", TRUE);
  1167.  
  1168.         if (!iff.raw)
  1169.         {   strcpy(tempstring1, "© Copyright:        ");
  1170.             strcat(tempstring1, contents[which].DataPtr);
  1171.             addreactionnode(&List2, tempstring1);
  1172.     }   }
  1173.     elif (!stricmp(contents[which].name, "AUTH"))
  1174.     {   chunkdesc("Author", TRUE);
  1175.  
  1176.         if (!iff.raw)
  1177.         {   strcpy(tempstring1, "Author:             ");
  1178.             strcat(tempstring1, contents[which].DataPtr);
  1179.             addreactionnode(&List2, tempstring1);
  1180.     }   }
  1181.     elif (!stricmp(contents[which].name, "ANNO"))
  1182.     {   chunkdesc("Annotation", TRUE);
  1183.  
  1184.         if (!iff.raw)
  1185.         {   strcpy(tempstring1, "Annotation:         ");
  1186.             strcat(tempstring1, contents[which].DataPtr);
  1187.             addreactionnode(&List2, tempstring1);
  1188.     }   }
  1189.     elif (!stricmp(contents[which].name, "NAME"))
  1190.     {   chunkdesc("Name", TRUE);
  1191.  
  1192.         if (!iff.raw)
  1193.         {   strcpy(tempstring1, "Name:               ");
  1194.             strcat(tempstring1, contents[which].DataPtr);
  1195.             addreactionnode(&List2, tempstring1);
  1196.     }   }
  1197.     elif (!stricmp(contents[which].name, "FVER"))
  1198.     {   chunkdesc("AmigaDOS version string", TRUE);
  1199.  
  1200.         if (!iff.raw)
  1201.         {   strcpy(tempstring1, "Version:            ");
  1202.             // bytes 0-5 are "$VER: "
  1203.             strcat(tempstring1, &contents[which].DataPtr[6]);
  1204.             addreactionnode(&List2, tempstring1);
  1205.     }   }
  1206.     elif
  1207.     (   (!stricmp(queryform, "FTXT") || !stricmp(queryform, "WORD"))
  1208.      && !stricmp(contents[which].name, "FSCC")
  1209.     )
  1210.     {   chunkdesc("Font/style/colour change", TRUE);
  1211.  
  1212.         if (!iff.raw)
  1213.         {
  1214.         strcpy(tempstring1, "Location:            ");
  1215.         uvalue = getuword(contents[which].DataPtr); // UWORD
  1216.         stcl_d(tempstring2, uvalue);
  1217.         strcat(tempstring1, tempstring2);
  1218.         addreactionnode(&List2, tempstring1);
  1219.  
  1220.         strcpy(tempstring1, "Font number:         ");
  1221.         uvalue = contents[which].DataPtr[2]; // UBYTE
  1222.         stcl_d(tempstring2, uvalue);
  1223.         strcat(tempstring1, tempstring2);
  1224.         addreactionnode(&List2, tempstring1);
  1225.  
  1226.         strcat(tempstring1, " Style:");
  1227.         addreactionnode(&List2, tempstring1);
  1228.  
  1229.         strcat(tempstring1, " Underlined?         ");
  1230.         if (contents[which].DataPtr[3] & 1)
  1231.         {   strcat(tempstring1, "Yes");
  1232.         } else strcat(tempstring1, "No");
  1233.         addreactionnode(&List2, tempstring1);
  1234.  
  1235.         strcat(tempstring1, " Bold?               ");
  1236.         if (contents[which].DataPtr[3] & 2)
  1237.         {   strcat(tempstring1, "Yes");
  1238.         } else strcat(tempstring1, "No");
  1239.         addreactionnode(&List2, tempstring1);
  1240.  
  1241.         strcat(tempstring1, " Italic?             ");
  1242.         if (contents[which].DataPtr[3] & 4)
  1243.         {   strcat(tempstring1, "Yes");
  1244.         } else strcat(tempstring1, "No");
  1245.         addreactionnode(&List2, tempstring1);
  1246.  
  1247.             strcat(tempstring1, " Extended?           ");
  1248.             if (contents[which].DataPtr[3] & 8)
  1249.             {   strcat(tempstring1, "Yes");
  1250.             } else strcat(tempstring1, "No");
  1251.             addreactionnode(&List2, tempstring1);
  1252.  
  1253.             strcat(tempstring1, " ColourFont?         ");
  1254.             if (contents[which].DataPtr[3] & 64)
  1255.             {   strcat(tempstring1, "Yes");
  1256.             } else strcat(tempstring1, "No");
  1257.             addreactionnode(&List2, tempstring1);
  1258.  
  1259.             strcat(tempstring1, " Tagged?             ");
  1260.             if (contents[which].DataPtr[3] & 128)
  1261.             {   strcat(tempstring1, "Yes");
  1262.             } else strcat(tempstring1, "No");
  1263.             addreactionnode(&List2, tempstring1);
  1264.  
  1265.             strcpy(tempstring1, "Miscellaneous style: ");
  1266.             if (contents[which].DataPtr[4] == 0)
  1267.             {   strcat(tempstring1, "None");
  1268.             } elif (contents[which].DataPtr[4] == 1)
  1269.             {   strcat(tempstring1, "Superscript");
  1270.             } elif (contents[which].DataPtr[4] == 2)
  1271.             {   strcat(tempstring1, "Subscript");
  1272.             } else
  1273.             {   strcat(tempstring1, "?");
  1274.             }
  1275.             addreactionnode(&List2, tempstring1);
  1276.  
  1277.             strcpy(tempstring1, "Colour:              ");
  1278.             uvalue = contents[which].DataPtr[5]; // UBYTE
  1279.             stcl_d(tempstring2, uvalue);
  1280.             strcat(tempstring1, tempstring2);
  1281.             addreactionnode(&List2, tempstring1);
  1282.     }   }
  1283.     elif (!strcmp(queryform, "FTXT"))
  1284.     {   if (!strcmp(contents[which].name, "FONS"))
  1285.         {   chunkdesc("Font specifier", TRUE);
  1286.  
  1287.         if (!iff.raw)
  1288.         {
  1289.             strcpy(tempstring1, "ID number:          ");
  1290.             stcl_d(tempstring2, contents[which].DataPtr[0]);
  1291.             strcat(tempstring1, tempstring2);
  1292.             if (contents[which].DataPtr[0] > 9)
  1293.             {   strcat(tempstring1, " (invalid)");
  1294.             }
  1295.             addreactionnode(&List2, tempstring1);
  1296.  
  1297.             // Next is a pad byte ([1]).
  1298.  
  1299.             strcpy(tempstring1, "Proportional?       ");
  1300.             uvalue = contents[which].DataPtr[2];
  1301.             if (uvalue == 0)
  1302.             {   strcat(tempstring1, "Unknown");
  1303.             } elif (uvalue == 1)
  1304.             {   strcat(tempstring1, "No");
  1305.             } elif (uvalue == 2)
  1306.             {   strcat(tempstring1, "Yes");
  1307.             } else strcat(tempstring1, "?"); // not the same as `Unknown', of course!
  1308.             addreactionnode(&List2, tempstring1);
  1309.  
  1310.             strcpy(tempstring1, "Serifs?             ");
  1311.             uvalue = contents[which].DataPtr[3];
  1312.             if (uvalue == 0)
  1313.             {   strcat(tempstring1, "Unknown");
  1314.             } elif (uvalue == 1)
  1315.             {   strcat(tempstring1, "No");
  1316.             } elif (uvalue == 2)
  1317.             {   strcat(tempstring1, "Yes");
  1318.             } else strcat(tempstring1, "?"); // not the same as `Unknown', of course!
  1319.             addreactionnode(&List2, tempstring1);
  1320.  
  1321.             strcpy(tempstring1, "Font name:          ");
  1322.             strcat(tempstring1, &(contents[which].DataPtr[4]));
  1323.             addreactionnode(&List2, tempstring1);
  1324.         }   }
  1325.         elif (!strcmp(contents[which].name, "CHRS"))
  1326.         {   chunkdesc("Stream of text", FALSE);
  1327.     }   }
  1328.     elif (!strcmp(queryform, "PREF"))
  1329.     {   if (!strcmp(contents[which].name, "ICTL"))
  1330.         {   chunkdesc("IControl preferences", TRUE);
  1331.  
  1332.         if (!iff.raw)
  1333.         {
  1334.             strcpy(tempstring1, "Verify timeout:         ");
  1335.             uvalue = getuword(&(contents[which].DataPtr[16]));
  1336.             stcl_d(tempstring2, uvalue);
  1337.             strcat(tempstring1, tempstring2);
  1338.             addreactionnode(&List2, tempstring1);
  1339.  
  1340.             strcpy(tempstring1, "Meta drag mouse event:  ");
  1341.             svalue = getsword(&(contents[which].DataPtr[18]));
  1342.             stcl_d(tempstring2, svalue);
  1343.             strcat(tempstring1, tempstring2);
  1344.             addreactionnode(&List2, tempstring1);
  1345.  
  1346.             addreactionnode(&List2, "Flags:");
  1347.             uvalue = getulong(&(contents[which].DataPtr[20]));
  1348.  
  1349.             strcpy(tempstring1, " Coerce colours?        ");
  1350.             if (uvalue & 1) // ICF_COERCE_COLORS
  1351.             {   strcat(tempstring1, "Yes");
  1352.             } else strcat(tempstring1, "No");
  1353.             addreactionnode(&List2, tempstring1);
  1354.  
  1355.             strcpy(tempstring1, " Coerce interlace?      ");
  1356.             if (uvalue & 2) // ICF_COERCE_LACE
  1357.             {   strcat(tempstring1, "Yes");
  1358.             } else strcat(tempstring1, "No");
  1359.             addreactionnode(&List2, tempstring1);
  1360.  
  1361.             strcpy(tempstring1, " String gadget filter?  ");
  1362.             if (uvalue & 4) // ICF_STRGAD_FILTER
  1363.             {   strcat(tempstring1, "Yes");
  1364.             } else strcat(tempstring1, "No");
  1365.             addreactionnode(&List2, tempstring1);
  1366.  
  1367.             strcpy(tempstring1, " Menu snap?             ");
  1368.             if (uvalue & 8) // ICF_MENUSNAP
  1369.             {   strcat(tempstring1, "Yes");
  1370.             } else strcat(tempstring1, "No");
  1371.             addreactionnode(&List2, tempstring1);
  1372.  
  1373.             strcpy(tempstring1, " Mode promotion?        ");
  1374.             if (uvalue & 16) // ICF_MODEPROMOTE
  1375.             {   strcat(tempstring1, "Yes");
  1376.             } else strcat(tempstring1, "No");
  1377.             addreactionnode(&List2, tempstring1);
  1378.  
  1379.             strcpy(tempstring1, " Square ratio?          "); // this one is new for OS3.9
  1380.             if (uvalue & 32) // ICF_SQUARE_RATIO
  1381.             {   strcat(tempstring1, "Yes");
  1382.             } else strcat(tempstring1, "No");
  1383.             addreactionnode(&List2, tempstring1);
  1384.  
  1385.             addreactionnode(&List2, "Command keys:");
  1386.  
  1387.             strcat(tempstring1, " Workbench to front:    ");
  1388.             stcl_d(tempstring2, contents[which].DataPtr[24]);
  1389.             strcat(tempstring1, tempstring2);
  1390.             addreactionnode(&List2, tempstring1);
  1391.  
  1392.             strcat(tempstring1, " Front screen to back:  ");
  1393.             stcl_d(tempstring2, contents[which].DataPtr[25]);
  1394.             strcat(tempstring1, tempstring2);
  1395.             addreactionnode(&List2, tempstring1);
  1396.  
  1397.             strcat(tempstring1, " Requester TRUE:        ");
  1398.             stcl_d(tempstring2, contents[which].DataPtr[26]);
  1399.             strcat(tempstring1, tempstring2);
  1400.             addreactionnode(&List2, tempstring1);
  1401.  
  1402.             strcat(tempstring1, " Requester FALSE:       ");
  1403.             stcl_d(tempstring2, contents[which].DataPtr[27]);
  1404.             strcat(tempstring1, tempstring2);
  1405.             addreactionnode(&List2, tempstring1);
  1406.         }   }
  1407.         elif (!strcmp(contents[which].name, "SERL"))
  1408.         {   chunkdesc("Serial preferences", TRUE);
  1409.  
  1410.         if (!iff.raw)
  1411.         {
  1412.             strcpy(tempstring1, "Unit 0 mapping:         ");
  1413.             uvalue = getulong(&(contents[which].DataPtr[12]));
  1414.             stcl_d(tempstring2, uvalue);
  1415.             strcat(tempstring1, tempstring2);
  1416.             addreactionnode(&List2, tempstring1);
  1417.  
  1418.             strcpy(tempstring1, "Baud rate:              ");
  1419.             uvalue = getulong(&(contents[which].DataPtr[16]));
  1420.             stcl_d(tempstring2, uvalue);
  1421.             strcat(tempstring1, tempstring2);
  1422.             strcat(tempstring1, " bps");
  1423.             addreactionnode(&List2, tempstring1);
  1424.  
  1425.             strcpy(tempstring1, "Input buffer size:      ");
  1426.             uvalue = getulong(&(contents[which].DataPtr[20]));
  1427.             stcl_d(tempstring2, uvalue);
  1428.             strcat(tempstring1, tempstring2);
  1429.             if (uvalue > 65536)
  1430.             {   strcat(tempstring1, "!");
  1431.             }
  1432.             addreactionnode(&List2, tempstring1);
  1433.  
  1434.             strcpy(tempstring1, "Output buffer size:     ");
  1435.             uvalue = getulong(&(contents[which].DataPtr[24]));
  1436.             stcl_d(tempstring2, uvalue);
  1437.             strcat(tempstring1, tempstring2);
  1438.             if (uvalue > 65536)
  1439.             {   strcat(tempstring1, "!");
  1440.             }
  1441.             addreactionnode(&List2, tempstring1);
  1442.  
  1443.             strcpy(tempstring1, "Input handshaking:      ");
  1444.             if (contents[which].DataPtr[28] == 0)
  1445.             {   strcat(tempstring1, "0 (XON)");  // HSHAKE_XON
  1446.             } elif (contents[which].DataPtr[28] == 1)
  1447.             {   strcat(tempstring1, "1 (RTS)");  // HSHAKE_RTS
  1448.             } elif (contents[which].DataPtr[28] == 2)
  1449.             {   strcat(tempstring1, "2 (None)"); // HSHAKE_NONE
  1450.             } else
  1451.             {   strcat(tempstring1, "?");
  1452.             }
  1453.             addreactionnode(&List2, tempstring1);
  1454.  
  1455.             strcpy(tempstring1, "Output handshaking:     ");
  1456.             if (contents[which].DataPtr[29] == 0)
  1457.             {   strcat(tempstring1, "0 (XON)");  // HSHAKE_XON
  1458.             } elif (contents[which].DataPtr[29] == 1)
  1459.             {   strcat(tempstring1, "1 (RTS)");  // HSHAKE_RTS
  1460.             } elif (contents[which].DataPtr[29] == 2)
  1461.             {   strcat(tempstring1, "2 (None)"); // HSHAKE_NONE
  1462.             } else
  1463.             {   strcat(tempstring1, "?");
  1464.             }
  1465.             addreactionnode(&List2, tempstring1);
  1466.  
  1467.             strcpy(tempstring1, "Parity:                 ");
  1468.             if (contents[which].DataPtr[30] == 0)
  1469.             {   strcat(tempstring1, "0 (None)");  // PARITY_NONE
  1470.             } elif (contents[which].DataPtr[30] == 1)
  1471.             {   strcat(tempstring1, "1 (Even)");  // PARITY_EVEN
  1472.             } elif (contents[which].DataPtr[30] == 2)
  1473.             {   strcat(tempstring1, "2 (Odd)");   // PARITY_ODD
  1474.             } elif (contents[which].DataPtr[30] == 3)
  1475.             {   strcat(tempstring1, "3 (Mark)");  // PARITY_MARK
  1476.             } elif (contents[which].DataPtr[30] == 4)
  1477.             {   strcat(tempstring1, "4 (Space)"); // PARITY_SPACE
  1478.             } else
  1479.             {   strcat(tempstring1, "?");
  1480.             }
  1481.             addreactionnode(&List2, tempstring1);
  1482.  
  1483.             strcpy(tempstring1, "I/O bits per character: ");
  1484.             stcl_d(tempstring2, contents[which].DataPtr[31]);
  1485.             strcat(tempstring1, tempstring2);
  1486.             addreactionnode(&List2, tempstring1);
  1487.  
  1488.             strcpy(tempstring1, "Stop bits:              ");
  1489.             stcl_d(tempstring2, contents[which].DataPtr[32]);
  1490.             strcat(tempstring1, tempstring2);
  1491.             addreactionnode(&List2, tempstring1);
  1492.         }   }
  1493.         elif (!strcmp(contents[which].name, "ASL "))
  1494.         {   chunkdesc("ASL preferences", TRUE);
  1495.  
  1496.             // 16 reserved bytes at start
  1497.  
  1498.             if (!iff.raw)
  1499.             {   strcpy(tempstring1, "Sort by:                ");
  1500.                 if (contents[which].DataPtr[16] == 0)
  1501.                 {   strcat(tempstring1, "0 (name)");
  1502.                 } elif (contents[which].DataPtr[16] == 1)
  1503.                 {   strcat(tempstring1, "1 (date)");
  1504.                 } elif (contents[which].DataPtr[16] == 2)
  1505.                 {   strcat(tempstring1, "2 (size)");
  1506.                 } else
  1507.                 {   strcat(tempstring1, "?");
  1508.                 }
  1509.                 addreactionnode(&List2, tempstring1);
  1510.  
  1511.                 strcpy(tempstring1, "Sort drawers:           ");
  1512.                 if (contents[which].DataPtr[17] == 0)
  1513.                 {   strcat(tempstring1, "0 (first)");
  1514.                 } elif (contents[which].DataPtr[17] == 1)
  1515.                 {   strcat(tempstring1, "1 (mix)");
  1516.                 } elif (contents[which].DataPtr[17] == 2)
  1517.                 {   strcat(tempstring1, "2 (last)");
  1518.                 } else
  1519.                 {   strcat(tempstring1, "?");
  1520.                 }
  1521.                 addreactionnode(&List2, tempstring1);
  1522.  
  1523.                 strcpy(tempstring1, "Sort order:             ");
  1524.                 if (contents[which].DataPtr[18] == 0)
  1525.                 {   strcat(tempstring1, "0 (ascending)");
  1526.                 } elif (contents[which].DataPtr[18] == 1)
  1527.                 {   strcat(tempstring1, "1 (descending)");
  1528.                 } else
  1529.                 {   strcat(tempstring1, "?");
  1530.                 }
  1531.                 addreactionnode(&List2, tempstring1);
  1532.  
  1533.                 strcpy(tempstring1, "Override?               ");
  1534.                 if (contents[which].DataPtr[19] & 64)
  1535.                 {   strcat(tempstring1, "Yes");
  1536.                 } else
  1537.                 {   strcat(tempstring1, "No");
  1538.                 }
  1539.                 addreactionnode(&List2, tempstring1);
  1540.  
  1541.                 strcpy(tempstring1, "Relative?               ");
  1542.                 if (contents[which].DataPtr[19] & 16)
  1543.                 {   strcat(tempstring1, "Yes");
  1544.                 } else
  1545.                 {   strcat(tempstring1, "No");
  1546.                 }
  1547.                 addreactionnode(&List2, tempstring1);
  1548.  
  1549.                 strcpy(tempstring1, "Position:               ");
  1550.                 if (contents[which].DataPtr[19] % 16 == 0)
  1551.                 {   strcat(tempstring1, "0 (default)");
  1552.                 } elif (contents[which].DataPtr[19] % 16 == 1)
  1553.                 {   strcat(tempstring1, "1 (center in window)");
  1554.                 } elif (contents[which].DataPtr[19] % 16 == 2)
  1555.                 {   strcat(tempstring1, "2 (center on screen)");
  1556.                 } elif (contents[which].DataPtr[19] % 16 == 3)
  1557.                 {   strcat(tempstring1, "3 (top left of window)");
  1558.                 } elif (contents[which].DataPtr[19] % 16 == 4)
  1559.                 {   strcat(tempstring1, "4 (top left of screen)");
  1560.                 } elif (contents[which].DataPtr[19] % 16 == 5)
  1561.                 {   strcat(tempstring1, "5 (mouse pointer)");
  1562.                 } else
  1563.                 {   strcat(tempstring1, "?");
  1564.                 }
  1565.                 addreactionnode(&List2, tempstring1);
  1566.  
  1567.                 strcpy(tempstring1, "Left edge:              ");
  1568.                 svalue = getsword(&(contents[which].DataPtr[20]));
  1569.                 stcl_d(tempstring2, uvalue);
  1570.                 strcat(tempstring1, tempstring2);
  1571.                 addreactionnode(&List2, tempstring1);
  1572.  
  1573.                 strcpy(tempstring1, "Top edge:               ");
  1574.                 svalue = getsword(&(contents[which].DataPtr[22]));
  1575.                 stcl_d(tempstring2, uvalue);
  1576.                 strcat(tempstring1, tempstring2);
  1577.                 addreactionnode(&List2, tempstring1);
  1578.  
  1579.                 strcpy(tempstring1, "Relative width:         ");
  1580.                 stcl_d(tempstring2, contents[which].DataPtr[24]);
  1581.                 strcat(tempstring1, tempstring2);
  1582.                 if (contents[which].DataPtr[24] < 25 || contents[which].DataPtr[24] > 100)
  1583.                 {   strcat(tempstring1, "!");
  1584.                 }
  1585.                 strcat(tempstring1, "%");
  1586.                 addreactionnode(&List2, tempstring1);
  1587.  
  1588.                 strcpy(tempstring1, "Relative height:        ");
  1589.                 stcl_d(tempstring2, contents[which].DataPtr[25]);
  1590.                 strcat(tempstring1, tempstring2);
  1591.                 if (contents[which].DataPtr[25] < 25 || contents[which].DataPtr[25] > 100)
  1592.                 {   strcat(tempstring1, "!");
  1593.                 }
  1594.                 strcat(tempstring1, "%");
  1595.                 addreactionnode(&List2, tempstring1);
  1596.         }   }
  1597.         elif (!strcmp(contents[which].name, "FONT"))
  1598.         {   chunkdesc("Font preferences", TRUE);
  1599.  
  1600.             // 14 reserved bytes at start
  1601.  
  1602.         if (!iff.raw)
  1603.         {
  1604.             strcpy(tempstring1, "Type:                   ");
  1605.             uvalue = getuword(&(contents[which].DataPtr[14]));
  1606.             if (uvalue == 0)
  1607.             {   strcat(tempstring1, "0 (Workbench)");
  1608.             } elif (uvalue == 1)
  1609.             {   strcat(tempstring1, "1 (system)");
  1610.             } elif (uvalue == 2)
  1611.             {   strcat(tempstring1, "2 (screen)");
  1612.             } else
  1613.             {   strcat(tempstring1, "?");
  1614.             }
  1615.             addreactionnode(&List2, tempstring1);
  1616.  
  1617.             strcpy(tempstring1, "Front pen:              ");
  1618.             stcl_d(tempstring2, contents[which].DataPtr[16]);
  1619.             strcat(tempstring1, tempstring2);
  1620.             addreactionnode(&List2, tempstring1);
  1621.  
  1622.             strcpy(tempstring1, "Back pen:               ");
  1623.             stcl_d(tempstring2, contents[which].DataPtr[17]);
  1624.             strcat(tempstring1, tempstring2);
  1625.             addreactionnode(&List2, tempstring1);
  1626.  
  1627.             strcpy(tempstring1, "Draw mode:              ");
  1628.             if (contents[which].DataPtr[18] == 0) // JAM1
  1629.             {   strcat(tempstring1, "0 (JAM1)");
  1630.             } elif (contents[which].DataPtr[18] == 1) // JAM2
  1631.             {   strcat(tempstring1, "1 (JAM2)");
  1632.             } elif (contents[which].DataPtr[18] == 2) // COMPLEMENT
  1633.             {   strcat(tempstring1, "2 (complement)");
  1634.             } elif (contents[which].DataPtr[18] == 3) // INVERSVID
  1635.             {   strcat(tempstring1, "3 (inverse video)");
  1636.             } else
  1637.             {   strcat(tempstring1, "?");
  1638.             }
  1639.             addreactionnode(&List2, tempstring1);
  1640.  
  1641.             /* Now we have an undocumented pad byte, necessary for
  1642.             structure alignment purposes. */
  1643.  
  1644.             addreactionnode(&List2, "Text attributes:");
  1645.  
  1646.             dotextattr(&contents[which].DataPtr[20]);
  1647.  
  1648.             strcpy(tempstring1, "Name:                   ");
  1649.             strcat(tempstring1, &(contents[which].DataPtr[28]));
  1650.             addreactionnode(&List2, tempstring1);
  1651.         }   }
  1652.         elif (!strcmp(contents[which].name, "INPT"))
  1653.         {   chunkdesc("Input preferences", TRUE);
  1654.  
  1655.             // The first 16 bytes are a keymap, currently ignored
  1656.  
  1657.         if (!iff.raw)
  1658.         {
  1659.             strcpy(tempstring1, "Pointer sensitivity:    ");
  1660.             uvalue = getuword(&(contents[which].DataPtr[16]));
  1661.             stcl_d(tempstring2, uvalue);
  1662.             strcat(tempstring1, tempstring2);
  1663.             strcat(tempstring1, " ticks");
  1664.             addreactionnode(&List2, tempstring1);
  1665.  
  1666.             addreactionnode(&List2, "Double-click interval:");
  1667.  
  1668.             strcpy(tempstring1, " Seconds:               ");
  1669.             uvalue = getulong(&(contents[which].DataPtr[18]));
  1670.             stcl_d(tempstring2, uvalue);
  1671.             strcat(tempstring1, tempstring2);
  1672.             addreactionnode(&List2, tempstring1);
  1673.  
  1674.             strcpy(tempstring1, " Microseconds:          ");
  1675.             uvalue = getulong(&(contents[which].DataPtr[22]));
  1676.             stcl_d(tempstring2, uvalue);
  1677.             strcat(tempstring1, tempstring2);
  1678.             addreactionnode(&List2, tempstring1);
  1679.  
  1680.             addreactionnode(&List2, "Key repeat delay:");
  1681.  
  1682.             strcpy(tempstring1, " Seconds:               ");
  1683.             uvalue = getulong(&(contents[which].DataPtr[26]));
  1684.             stcl_d(tempstring2, uvalue);
  1685.             strcat(tempstring1, tempstring2);
  1686.             addreactionnode(&List2, tempstring1);
  1687.  
  1688.             strcpy(tempstring1, " Microseconds:          ");
  1689.             uvalue = getulong(&(contents[which].DataPtr[30]));
  1690.             stcl_d(tempstring2, uvalue);
  1691.             strcat(tempstring1, tempstring2);
  1692.             addreactionnode(&List2, tempstring1);
  1693.  
  1694.             addreactionnode(&List2, "Key repeat speed:");
  1695.  
  1696.             strcpy(tempstring1, " Seconds:               ");
  1697.             uvalue = getulong(&(contents[which].DataPtr[34]));
  1698.             stcl_d(tempstring2, uvalue);
  1699.             strcat(tempstring1, tempstring2);
  1700.             addreactionnode(&List2, tempstring1);
  1701.  
  1702.             strcpy(tempstring1, " Microseconds:          ");
  1703.             uvalue = getulong(&(contents[which].DataPtr[38]));
  1704.             stcl_d(tempstring2, uvalue);
  1705.             strcat(tempstring1, tempstring2);
  1706.             addreactionnode(&List2, tempstring1);
  1707.  
  1708.             strcpy(tempstring1, "Mouse acceleration:     ");
  1709.             svalue = getsword(&(contents[which].DataPtr[42]));
  1710.             stcl_d(tempstring2, svalue);
  1711.             strcat(tempstring1, tempstring2);
  1712.             addreactionnode(&List2, tempstring1);
  1713.         }   }
  1714.         elif (!strcmp(contents[which].name, "OSCN"))
  1715.         {   chunkdesc("Overscan preferences", TRUE);
  1716.  
  1717.         if (!iff.raw)
  1718.         {
  1719.             strcpy(tempstring1, "Magic?                  ");
  1720.             uvalue = getulong(&(contents[which].DataPtr[4]));
  1721.             if (uvalue == 0xFEDCBA89) // OSCAN_MAGIC
  1722.             {   strcat(tempstring1, "Yes");
  1723.             } else
  1724.             {   strcat(tempstring1, "No");
  1725.             }
  1726.             addreactionnode(&List2, tempstring1);
  1727.  
  1728.             strcpy(tempstring1, "Horizontal start:       ");
  1729.             uvalue = getuword(&(contents[which].DataPtr[8]));
  1730.             stcl_d(tempstring2, uvalue);
  1731.             strcat(tempstring1, tempstring2);
  1732.             addreactionnode(&List2, tempstring1);
  1733.  
  1734.             strcpy(tempstring1, "Horizontal stop:        ");
  1735.             uvalue = getuword(&(contents[which].DataPtr[10]));
  1736.             stcl_d(tempstring2, uvalue);
  1737.             strcat(tempstring1, tempstring2);
  1738.             addreactionnode(&List2, tempstring1);
  1739.  
  1740.             strcpy(tempstring1, "Vertical start:         ");
  1741.             uvalue = getuword(&(contents[which].DataPtr[12]));
  1742.             stcl_d(tempstring2, uvalue);
  1743.             strcat(tempstring1, tempstring2);
  1744.             addreactionnode(&List2, tempstring1);
  1745.  
  1746.             strcpy(tempstring1, "Vertical stop:          ");
  1747.             uvalue = getuword(&(contents[which].DataPtr[14]));
  1748.             stcl_d(tempstring2, uvalue);
  1749.             strcat(tempstring1, tempstring2);
  1750.             addreactionnode(&List2, tempstring1);
  1751.  
  1752.             strcpy(tempstring1, "DisplayID:              ");
  1753.             uvalue = getulong(&(contents[which].DataPtr[16]));
  1754.             stcl_d(tempstring2, uvalue);
  1755.             strcat(tempstring1, tempstring2);
  1756.             addreactionnode(&List2, tempstring1);
  1757.  
  1758.             strcpy(tempstring1, "View offset:            ");
  1759.             svalue = getsword(&(contents[which].DataPtr[20]));
  1760.             stcl_d(tempstring2, svalue);
  1761.             strcat(tempstring1, tempstring2);
  1762.             strcat(tempstring1, ",");
  1763.             svalue = getsword(&(contents[which].DataPtr[22]));
  1764.             stcl_d(tempstring2, svalue);
  1765.             strcat(tempstring1, tempstring2);
  1766.             addreactionnode(&List2, tempstring1);
  1767.  
  1768.             strcpy(tempstring1, "Text overscan size:     ");
  1769.             svalue = getsword(&(contents[which].DataPtr[24]));
  1770.             stcl_d(tempstring2, svalue);
  1771.             strcat(tempstring1, tempstring2);
  1772.             strcat(tempstring1, ",");
  1773.             svalue = getsword(&(contents[which].DataPtr[26]));
  1774.             stcl_d(tempstring2, svalue);
  1775.             strcat(tempstring1, tempstring2);
  1776.             addreactionnode(&List2, tempstring1);
  1777.  
  1778.             addreactionnode(&List2, "Standard overscan size:");
  1779.  
  1780.             strcpy(tempstring1, " Top-left corner:       ");
  1781.             svalue = getsword(&(contents[which].DataPtr[28]));
  1782.             stcl_d(tempstring2, svalue);
  1783.             strcat(tempstring1, tempstring2);
  1784.             strcat(tempstring1, ",");
  1785.             svalue = getsword(&(contents[which].DataPtr[30]));
  1786.             stcl_d(tempstring2, svalue);
  1787.             strcat(tempstring1, tempstring2);
  1788.             addreactionnode(&List2, tempstring1);
  1789.  
  1790.             strcpy(tempstring1, " Bottom-right corner:   ");
  1791.             svalue = getsword(&(contents[which].DataPtr[32]));
  1792.             stcl_d(tempstring2, svalue);
  1793.             strcat(tempstring1, tempstring2);
  1794.             strcat(tempstring1, ",");
  1795.             svalue = getsword(&(contents[which].DataPtr[34]));
  1796.             stcl_d(tempstring2, svalue);
  1797.             strcat(tempstring1, tempstring2);
  1798.             addreactionnode(&List2, tempstring1);
  1799.         }   }
  1800.         elif (!strcmp(contents[which].name, "SCRM"))
  1801.         {   chunkdesc("Screen mode preferences", TRUE);
  1802.  
  1803.         if (!iff.raw)
  1804.         {
  1805.             strcpy(tempstring1, "DisplayID:              ");
  1806.             uvalue = getulong(&(contents[which].DataPtr[16]));
  1807.             stcl_d(tempstring2, uvalue);
  1808.             strcat(tempstring1, tempstring2);
  1809.             addreactionnode(&List2, tempstring1);
  1810.  
  1811.             strcpy(tempstring1, "Screen width:           ");
  1812.             uvalue = getuword(&(contents[which].DataPtr[20]));
  1813.             stcl_d(tempstring2, uvalue);
  1814.             strcat(tempstring1, tempstring2);
  1815.             addreactionnode(&List2, tempstring1);
  1816.  
  1817.             strcpy(tempstring1, "Screen height:          ");
  1818.             uvalue = getuword(&(contents[which].DataPtr[22]));
  1819.             stcl_d(tempstring2, uvalue);
  1820.             strcat(tempstring1, tempstring2);
  1821.             addreactionnode(&List2, tempstring1);
  1822.  
  1823.             strcpy(tempstring1, "Screen depth:           ");
  1824.             uvalue = getuword(&(contents[which].DataPtr[24]));
  1825.             stcl_d(tempstring2, uvalue);
  1826.             strcat(tempstring1, tempstring2);
  1827.             addreactionnode(&List2, tempstring1);
  1828.  
  1829.             strcpy(tempstring1, "Autoscroll?             ");
  1830.             uvalue = getuword(&(contents[which].DataPtr[26]));
  1831.             if (uvalue & 1) // SMB_AUTOSCROLL
  1832.             {   strcat(tempstring1, "Yes");
  1833.             } else
  1834.             {   strcat(tempstring1, "No");
  1835.             }
  1836.             addreactionnode(&List2, tempstring1);
  1837.         }   }
  1838.         elif (!strcmp(contents[which].name, "PSPD"))
  1839.         {   chunkdesc("PostScript printer preferences", TRUE);
  1840.  
  1841.         if (!iff.raw)
  1842.         {   addreactionnode(&List2, "Global attributes:");
  1843.  
  1844.             strcpy(tempstring1, " Driver mode:           ");
  1845.             if (contents[which].DataPtr[16] == 0) // DM_POSTSCRIPT
  1846.             {   strcat(tempstring1, "0 (PostScript)");
  1847.             } elif (contents[which].DataPtr[16] == 1) // DM_PASSTHROUGH
  1848.             {   strcat(tempstring1, "1 (pass through)");
  1849.             } else
  1850.             {   strcat(tempstring1, "?");
  1851.             }
  1852.             addreactionnode(&List2, tempstring1);
  1853.  
  1854.             strcpy(tempstring1, " Paper format:          ");
  1855.             if (contents[which].DataPtr[17] == 0) // PF_USLETTER
  1856.             {   strcat(tempstring1, "0 (US Letter)");
  1857.             } elif (contents[which].DataPtr[17] == 1) // PF_USLEGAL
  1858.             {   strcat(tempstring1, "1 (US Legal)");
  1859.             } elif (contents[which].DataPtr[17] == 2) // PF_A4
  1860.             {   strcat(tempstring1, "2 (A4)");
  1861.             } elif (contents[which].DataPtr[17] == 3) // PF_CUSTOM
  1862.             {   strcat(tempstring1, "3 (custom)");
  1863.             } else
  1864.             {   strcat(tempstring1, "?");
  1865.             }
  1866.             addreactionnode(&List2, tempstring1);
  1867.  
  1868.             // now two reserved bytes
  1869.  
  1870.             strcpy(tempstring1, " Copies:                ");
  1871.             svalue = getslong(&(contents[which].DataPtr[20]));
  1872.             stcl_d(tempstring2, svalue);
  1873.             strcat(tempstring1, tempstring2);
  1874.             addreactionnode(&List2, tempstring1);
  1875.  
  1876.             strcpy(tempstring1, " Paper width:           ");
  1877.             svalue = getslong(&(contents[which].DataPtr[24]));
  1878.             stcl_d(tempstring2, svalue);
  1879.             strcat(tempstring1, tempstring2);
  1880.             strcat(tempstring1, " millipoints");
  1881.             addreactionnode(&List2, tempstring1);
  1882.  
  1883.             strcpy(tempstring1, " Paper height:          ");
  1884.             svalue = getslong(&(contents[which].DataPtr[28]));
  1885.             stcl_d(tempstring2, svalue);
  1886.             strcat(tempstring1, tempstring2);
  1887.             strcat(tempstring1, " millipoints");
  1888.             addreactionnode(&List2, tempstring1);
  1889.  
  1890.             strcpy(tempstring1, " Horizontal DPI:        ");
  1891.             svalue = getslong(&(contents[which].DataPtr[32]));
  1892.             stcl_d(tempstring2, svalue);
  1893.             strcat(tempstring1, tempstring2);
  1894.             strcat(tempstring1, " millipoints");
  1895.             addreactionnode(&List2, tempstring1);
  1896.  
  1897.             strcpy(tempstring1, " Vertical DPI:          ");
  1898.             svalue = getslong(&(contents[which].DataPtr[36]));
  1899.             stcl_d(tempstring2, svalue);
  1900.             strcat(tempstring1, tempstring2);
  1901.             strcat(tempstring1, " millipoints");
  1902.             addreactionnode(&List2, tempstring1);
  1903.  
  1904.             addreactionnode(&List2, "Text options:");
  1905.  
  1906.             strcpy(tempstring1, " Font:                  ");
  1907.             if (contents[which].DataPtr[40] == 0)
  1908.             {   strcat(tempstring1, "0 (Courier)");
  1909.             } elif (contents[which].DataPtr[40] == 1)
  1910.             {   strcat(tempstring1, "1 (Times)");
  1911.             } elif (contents[which].DataPtr[40] == 2)
  1912.             {   strcat(tempstring1, "2 (Helvetica)");
  1913.             } elif (contents[which].DataPtr[40] == 3)
  1914.             {   strcat(tempstring1, "3 (Helvetica Narrow)");
  1915.             } elif (contents[which].DataPtr[40] == 4)
  1916.             {   strcat(tempstring1, "4 (Avant Garde)");
  1917.             } elif (contents[which].DataPtr[40] == 5)
  1918.             {   strcat(tempstring1, "5 (Bookman)");
  1919.             } elif (contents[which].DataPtr[40] == 6)
  1920.             {   strcat(tempstring1, "6 (New Century)");
  1921.             } elif (contents[which].DataPtr[40] == 7)
  1922.             {   strcat(tempstring1, "7 (Palantino)");
  1923.             } elif (contents[which].DataPtr[40] == 8)
  1924.             {   strcat(tempstring1, "8 (Zapf Chancery)");
  1925.             } else
  1926.             {   strcat(tempstring1, "?");
  1927.             }
  1928.             addreactionnode(&List2, tempstring1);
  1929.  
  1930.             strcpy(tempstring1, " Pitch:                 ");
  1931.             if (contents[which].DataPtr[41] == 0)
  1932.             {   strcat(tempstring1, "0 (normal)");
  1933.             } elif (contents[which].DataPtr[41] == 1)
  1934.             {   strcat(tempstring1, "1 (compressed)");
  1935.             } elif (contents[which].DataPtr[41] == 2)
  1936.             {   strcat(tempstring1, "2 (expanded)");
  1937.             } else
  1938.             {   strcat(tempstring1, "?");
  1939.             }
  1940.             addreactionnode(&List2, tempstring1);
  1941.  
  1942.             strcpy(tempstring1, " Orientation:           ");
  1943.             if (contents[which].DataPtr[42] == 0) // ORIENT_PORTRAIT
  1944.             {   strcat(tempstring1, "0 (portrait)");
  1945.             } elif (contents[which].DataPtr[42] == 1) // ORIENT_LANDSCAPE
  1946.             {   strcat(tempstring1, "1 (landscape)");
  1947.             } else
  1948.             {   strcat(tempstring1, "?");
  1949.             }
  1950.             addreactionnode(&List2, tempstring1);
  1951.  
  1952.             strcpy(tempstring1, " Tab stops:             ");
  1953.             if (contents[which].DataPtr[43] == 0) // TAB_4
  1954.             {   strcat(tempstring1, "0 (4 characters)");
  1955.             } elif (contents[which].DataPtr[43] == 1) // TAB_8
  1956.             {   strcat(tempstring1, "1 (8 characters)");
  1957.             } elif (contents[which].DataPtr[43] == 2) // TAB_QUART
  1958.             {   strcat(tempstring1, "2 (quarter-inch)");
  1959.             } elif (contents[which].DataPtr[43] == 3) // TAB_HALF
  1960.             {   strcat(tempstring1, "3 (half-inch)");
  1961.             } elif (contents[which].DataPtr[43] == 4) // TAB_INCH
  1962.             {   strcat(tempstring1, "4 (inch)");
  1963.             } else
  1964.             {   strcat(tempstring1, "?");
  1965.             }
  1966.             addreactionnode(&List2, tempstring1);
  1967.  
  1968.             // now eight reserved bytes
  1969.  
  1970.             addreactionnode(&List2, "Text dimensions:");
  1971.  
  1972.             strcpy(tempstring1, " Left margin:           ");
  1973.             svalue = getslong(&(contents[which].DataPtr[52]));
  1974.             stcl_d(tempstring2, svalue);
  1975.             strcat(tempstring1, tempstring2);
  1976.             strcat(tempstring1, " millipoints");
  1977.             addreactionnode(&List2, tempstring1);
  1978.  
  1979.             strcpy(tempstring1, " Right margin:          ");
  1980.             svalue = getslong(&(contents[which].DataPtr[56]));
  1981.             stcl_d(tempstring2, svalue);
  1982.             strcat(tempstring1, tempstring2);
  1983.             strcat(tempstring1, " millipoints");
  1984.             addreactionnode(&List2, tempstring1);
  1985.  
  1986.             strcpy(tempstring1, " Top margin:            ");
  1987.             svalue = getslong(&(contents[which].DataPtr[60]));
  1988.             stcl_d(tempstring2, svalue);
  1989.             strcat(tempstring1, tempstring2);
  1990.             strcat(tempstring1, " millipoints");
  1991.             addreactionnode(&List2, tempstring1);
  1992.  
  1993.             strcpy(tempstring1, " Bottom margin:         ");
  1994.             svalue = getslong(&(contents[which].DataPtr[64]));
  1995.             stcl_d(tempstring2, svalue);
  1996.             strcat(tempstring1, tempstring2);
  1997.             strcat(tempstring1, " millipoints");
  1998.             addreactionnode(&List2, tempstring1);
  1999.  
  2000.             strcpy(tempstring1, " Font size:             ");
  2001.             svalue = getslong(&(contents[which].DataPtr[68]));
  2002.             stcl_d(tempstring2, svalue);
  2003.             strcat(tempstring1, tempstring2);
  2004.             strcat(tempstring1, " millipoints");
  2005.             addreactionnode(&List2, tempstring1);
  2006.  
  2007.             strcpy(tempstring1, " Leading:               ");
  2008.             svalue = getslong(&(contents[which].DataPtr[72]));
  2009.             stcl_d(tempstring2, svalue);
  2010.             strcat(tempstring1, tempstring2);
  2011.             strcat(tempstring1, " millipoints");
  2012.             addreactionnode(&List2, tempstring1);
  2013.  
  2014.             // now eight reserved bytes
  2015.  
  2016.             addreactionnode(&List2, "Graphics options:");
  2017.  
  2018.             strcpy(tempstring1, " Left edge:             ");
  2019.             svalue = getslong(&(contents[which].DataPtr[80]));
  2020.             stcl_d(tempstring2, svalue);
  2021.             strcat(tempstring1, tempstring2);
  2022.             strcat(tempstring1, " millipoints");
  2023.             addreactionnode(&List2, tempstring1);
  2024.  
  2025.             strcpy(tempstring1, " Top edge:              ");
  2026.             svalue = getslong(&(contents[which].DataPtr[84]));
  2027.             stcl_d(tempstring2, svalue);
  2028.             strcat(tempstring1, tempstring2);
  2029.             strcat(tempstring1, " millipoints");
  2030.             addreactionnode(&List2, tempstring1);
  2031.  
  2032.             strcpy(tempstring1, " Width:                 ");
  2033.             svalue = getslong(&(contents[which].DataPtr[88]));
  2034.             stcl_d(tempstring2, svalue);
  2035.             strcat(tempstring1, tempstring2);
  2036.             strcat(tempstring1, " millipoints");
  2037.             addreactionnode(&List2, tempstring1);
  2038.  
  2039.             strcpy(tempstring1, " Height:                ");
  2040.             svalue = getslong(&(contents[which].DataPtr[92]));
  2041.             stcl_d(tempstring2, svalue);
  2042.             strcat(tempstring1, tempstring2);
  2043.             strcat(tempstring1, " millipoints");
  2044.             addreactionnode(&List2, tempstring1);
  2045.  
  2046.             strcpy(tempstring1, " Image:                 ");
  2047.             if (contents[which].DataPtr[96] == 0) // IM_POSITIVE
  2048.             {   strcat(tempstring1, "0 (positive)");
  2049.             } elif (contents[which].DataPtr[96] == 1) // IM_NEGATIVE
  2050.             {   strcat(tempstring1, "1 (negative)");
  2051.             } else
  2052.             {   strcat(tempstring1, "?");
  2053.             }
  2054.             addreactionnode(&List2, tempstring1);
  2055.  
  2056.             strcpy(tempstring1, " Shading:               ");
  2057.             if (contents[which].DataPtr[97] == 0) // SHAD_BW
  2058.             {   strcat(tempstring1, "0 (black and white)");
  2059.             } elif (contents[which].DataPtr[97] == 1) // SHAD_GREYSCALE
  2060.             {   strcat(tempstring1, "1 (greyscale)");
  2061.             } elif (contents[which].DataPtr[97] == 2) // SHAD_COLOR
  2062.             {   strcat(tempstring1, "2 (colour)");
  2063.             } else
  2064.             {   strcat(tempstring1, "?");
  2065.             }
  2066.             addreactionnode(&List2, tempstring1);
  2067.  
  2068.             strcpy(tempstring1, " Dithering:             ");
  2069.             if (contents[which].DataPtr[98] == 0) // DITH_DEFAULT
  2070.             {   strcat(tempstring1, "0 (default)");
  2071.             } elif (contents[which].DataPtr[98] == 1) // DITH_DOTTY
  2072.             {   strcat(tempstring1, "1 (dotty)");
  2073.             } elif (contents[which].DataPtr[98] == 2) // DITH_VERT
  2074.             {   strcat(tempstring1, "2 (vertical)");
  2075.             } elif (contents[which].DataPtr[98] == 3) // DITH_HORIZ
  2076.             {   strcat(tempstring1, "3 (horizontal)");
  2077.             } elif (contents[which].DataPtr[98] == 4) // DITH_DIAG
  2078.             {   strcat(tempstring1, "4 (diagonal)");
  2079.             } else
  2080.             {   strcat(tempstring1, "?");
  2081.             }
  2082.             addreactionnode(&List2, tempstring1);
  2083.  
  2084.             // now nine reserved bytes
  2085.  
  2086.             addreactionnode(&List2, "Graphics scaling:");
  2087.  
  2088.             strcpy(tempstring1, " Aspect:                ");
  2089.             if (contents[which].DataPtr[108] == 0) // ASP_HORIZ
  2090.             {   strcat(tempstring1, "0 (horizontal)");
  2091.             } elif (contents[which].DataPtr[108] == 1) // ASP_VERT
  2092.             {   strcat(tempstring1, "1 (vertical)");
  2093.             } else
  2094.             {   strcat(tempstring1, "?");
  2095.             }
  2096.             addreactionnode(&List2, tempstring1);
  2097.  
  2098.             strcpy(tempstring1, " Scaling type:          ");
  2099.             if (contents[which].DataPtr[109] == 0) // ST_ASPECT_ASIS
  2100.             {   strcat(tempstring1, "0 (aspect as is)");
  2101.             } elif (contents[which].DataPtr[109] == 1) // ST_ASPECT_WIDE
  2102.             {   strcat(tempstring1, "1 (aspect wide)");
  2103.             } elif (contents[which].DataPtr[109] == 2) // ST_ASPECT_TALL
  2104.             {   strcat(tempstring1, "2 (aspect tall)");
  2105.             } elif (contents[which].DataPtr[109] == 3) // ST_ASPECT_BOTH
  2106.             {   strcat(tempstring1, "3 (aspect both)");
  2107.             } elif (contents[which].DataPtr[109] == 4) // ST_FITS_WIDE
  2108.             {   strcat(tempstring1, "4 (fits wide)");
  2109.             } elif (contents[which].DataPtr[109] == 5) // ST_FITS_TALL
  2110.             {   strcat(tempstring1, "5 (fits tall)");
  2111.             } elif (contents[which].DataPtr[109] == 6) // ST_FITS_BOTH
  2112.             {   strcat(tempstring1, "6 (fits both)");
  2113.             } else
  2114.             {   strcat(tempstring1, "?");
  2115.             }
  2116.             addreactionnode(&List2, tempstring1);
  2117.  
  2118.             // now one reserved byte
  2119.  
  2120.             strcpy(tempstring1, " Centering:             ");
  2121.             if (contents[which].DataPtr[111] == 0) // CENT_NONE
  2122.             {   strcat(tempstring1, "0 (none)");
  2123.             } elif (contents[which].DataPtr[111] == 1) // CENT_HORIZ
  2124.             {   strcat(tempstring1, "1 (horizontal)");
  2125.             } elif (contents[which].DataPtr[111] == 2) // CENT_VERT
  2126.             {   strcat(tempstring1, "2 (vertical)");
  2127.             } elif (contents[which].DataPtr[111] == 3) // CENT_BOTH
  2128.             {   strcat(tempstring1, "3 (both)");
  2129.             } else
  2130.             {   strcat(tempstring1, "?");
  2131.             }
  2132.             addreactionnode(&List2, tempstring1);
  2133.         }   }
  2134.         elif (!strcmp(contents[which].name, "PGFX"))
  2135.         {   chunkdesc("Printer graphics preferences", TRUE);
  2136.  
  2137.         if (!iff.raw)
  2138.         {
  2139.             strcpy(tempstring1, "Aspect:                 ");
  2140.             uvalue = getuword(&(contents[which].DataPtr[16]));
  2141.             if (uvalue == 0) // PA_HORIZONTAL
  2142.             {   strcat(tempstring1, "0 (horizontal)");
  2143.             } elif (uvalue == 1) // PA_VERTICAL
  2144.             {   strcat(tempstring1, "1 (vertical)");
  2145.             } else
  2146.             {   strcat(tempstring1, "?");
  2147.             }
  2148.             addreactionnode(&List2, tempstring1);
  2149.  
  2150.             strcpy(tempstring1, "Shading:                ");
  2151.             uvalue = getuword(&(contents[which].DataPtr[18]));
  2152.             if (uvalue == 0) // PS_BW
  2153.             {   strcat(tempstring1, "0 (black and white)");
  2154.             } elif (uvalue == 1) // PS_GREYSCALE
  2155.             {   strcat(tempstring1, "1 (greyscale 1)");
  2156.             } elif (uvalue == 2) // PS_COLOR
  2157.             {   strcat(tempstring1, "2 (colour)");
  2158.             } elif (uvalue == 3) // PS_GREY_SCALE2
  2159.             {   strcat(tempstring1, "3 (greyscale 2)");
  2160.             } else
  2161.             {   strcat(tempstring1, "?");
  2162.             }
  2163.             addreactionnode(&List2, tempstring1);
  2164.  
  2165.             strcpy(tempstring1, "Image:                  ");
  2166.             uvalue = getuword(&(contents[which].DataPtr[20]));
  2167.             if (uvalue == 0) // PI_POSITIVE
  2168.             {   strcat(tempstring1, "0 (positive)");
  2169.             } elif (uvalue == 1) // PI_NEGATIVE
  2170.             {   strcat(tempstring1, "1 (negative)");
  2171.             } else
  2172.             {   strcat(tempstring1, "?");
  2173.             }
  2174.             addreactionnode(&List2, tempstring1);
  2175.  
  2176.             strcpy(tempstring1, "Threshold:              ");
  2177.             svalue = getsword(&(contents[which].DataPtr[22]));
  2178.             stcl_d(tempstring2, svalue);
  2179.             strcat(tempstring1, tempstring2);
  2180.             addreactionnode(&List2, tempstring1);
  2181.  
  2182.             addreactionnode(&List2, "Colour correction:");
  2183.  
  2184.             strcpy(tempstring1, " Red?                   ");
  2185.             if (contents[which].DataPtr[24] & 1) // PCCF_RED
  2186.             {   strcat(tempstring1, "Yes");
  2187.             } else
  2188.             {   strcat(tempstring1, "No");
  2189.             }
  2190.             addreactionnode(&List2, tempstring1);
  2191.  
  2192.             strcpy(tempstring1, " Green?                 ");
  2193.             if (contents[which].DataPtr[24] & 2) // PCCF_GREEN
  2194.             {   strcat(tempstring1, "Yes");
  2195.             } else
  2196.             {   strcat(tempstring1, "No");
  2197.             }
  2198.             addreactionnode(&List2, tempstring1);
  2199.  
  2200.             strcpy(tempstring1, " Blue?                  ");
  2201.             if (contents[which].DataPtr[24] & 4) // PCCF_BLUE
  2202.             {   strcat(tempstring1, "Yes");
  2203.             } else
  2204.             {   strcat(tempstring1, "No");
  2205.             }
  2206.             addreactionnode(&List2, tempstring1);
  2207.  
  2208.             strcpy(tempstring1, "Dimensions:             ");
  2209.             if (contents[which].DataPtr[25] == 0) // PD_IGNORE
  2210.             {   strcat(tempstring1, "0 (ignore)");
  2211.             } elif (contents[which].DataPtr[25] == 1) // PD_BOUNDED
  2212.             {   strcat(tempstring1, "1 (bounded)");
  2213.             } elif (contents[which].DataPtr[25] == 2) // PD_ABSOLUTE
  2214.             {   strcat(tempstring1, "2 (absolute)");
  2215.             } elif (contents[which].DataPtr[25] == 3) // PD_PIXEL
  2216.             {   strcat(tempstring1, "3 (printer pixels)");
  2217.             } elif (contents[which].DataPtr[25] == 4) // PD_MULTIPLY
  2218.             {   strcat(tempstring1, "4 (multiply)");
  2219.             } else
  2220.             {   strcat(tempstring1, "?");
  2221.             }
  2222.             addreactionnode(&List2, tempstring1);
  2223.  
  2224.             strcpy(tempstring1, "Dithering:              ");
  2225.             if (contents[which].DataPtr[26] == 0) // PD_ORDERED
  2226.             {   strcat(tempstring1, "0 (ordered)");
  2227.             } elif (contents[which].DataPtr[26] == 1) // PD_HALFTONE
  2228.             {   strcat(tempstring1, "1 (halftone)");
  2229.             } elif (contents[which].DataPtr[26] == 2) // PD_FLOYD
  2230.             {   strcat(tempstring1, "2 (Floyd-Steinberg)");
  2231.             } else
  2232.             {   strcat(tempstring1, "?");
  2233.             }
  2234.             addreactionnode(&List2, tempstring1);
  2235.  
  2236.             strcpy(tempstring1, "Flags:");
  2237.             uvalue = getuword(&(contents[which].DataPtr[27]));
  2238.  
  2239.             strcpy(tempstring1, " Centre image?          ");
  2240.             if (uvalue & 1) // PGFF_CENTER_IMAGE
  2241.             {   strcat(tempstring1, "Yes");
  2242.             } else
  2243.             {   strcat(tempstring1, "No");
  2244.             }
  2245.             addreactionnode(&List2, tempstring1);
  2246.  
  2247.             strcpy(tempstring1, " Integer scaling?       ");
  2248.             if (uvalue & 2) // PGFF_INTEGER_SCALING
  2249.             {   strcat(tempstring1, "Yes");
  2250.             } else
  2251.             {   strcat(tempstring1, "No");
  2252.             }
  2253.             addreactionnode(&List2, tempstring1);
  2254.  
  2255.             strcpy(tempstring1, " Antialiasing?          ");
  2256.             if (uvalue & 4) // PGFF_ANTI_ALIAS
  2257.             {   strcat(tempstring1, "Yes");
  2258.             } else
  2259.             {   strcat(tempstring1, "No");
  2260.             }
  2261.             addreactionnode(&List2, tempstring1);
  2262.  
  2263.             strcpy(tempstring1, "Print density:          ");
  2264.             stcl_d(tempstring2, contents[which].DataPtr[29]);
  2265.             strcat(tempstring1, tempstring2);
  2266.             if (contents[which].DataPtr[29] < 1 || contents[which].DataPtr[29] > 7)
  2267.             {   strcat(tempstring1, "!");
  2268.             }
  2269.             addreactionnode(&List2, tempstring1);
  2270.  
  2271.             strcpy(tempstring1, "Maximum width:          ");
  2272.             uvalue = getuword(&(contents[which].DataPtr[30]));
  2273.             stcl_d(tempstring2, uvalue);
  2274.             strcat(tempstring1, tempstring2);
  2275.             addreactionnode(&List2, tempstring1);
  2276.  
  2277.             strcpy(tempstring1, "Maximum height:         ");
  2278.             uvalue = getuword(&(contents[which].DataPtr[32]));
  2279.             stcl_d(tempstring2, uvalue);
  2280.             strcat(tempstring1, tempstring2);
  2281.             addreactionnode(&List2, tempstring1);
  2282.  
  2283.             strcpy(tempstring1, "Offset:                 ");
  2284.             stcl_d(tempstring2, contents[which].DataPtr[34]);
  2285.             strcat(tempstring1, tempstring2);
  2286.             strcat(tempstring1, ",");
  2287.             stcl_d(tempstring2, contents[which].DataPtr[35]);
  2288.             strcat(tempstring1, tempstring2);
  2289.             addreactionnode(&List2, tempstring1);
  2290.         }   }
  2291.         elif (!strcmp(contents[which].name, "PTXT"))
  2292.         {   chunkdesc("Printer text preferences", TRUE);
  2293.  
  2294.         if (!iff.raw)
  2295.         {
  2296.             strcpy(tempstring1, "Driver filename:        ");
  2297.             strcat(tempstring1, &(contents[which].DataPtr[16]));
  2298.             // 32-character field, so it doesn't need truncation
  2299.             addreactionnode(&List2, tempstring1);
  2300.  
  2301.             strcpy(tempstring1, "Port:                   ");
  2302.             if (contents[which].DataPtr[48] == 0) // PP_PARALLEL
  2303.             {   strcat(tempstring1, "0 (parallel)");
  2304.             } elif (contents[which].DataPtr[48] == 1) // PP_SERIAL
  2305.             {   strcat(tempstring1, "1 (serial)");
  2306.             } else
  2307.             {   strcat(tempstring1, "?");
  2308.             }
  2309.             addreactionnode(&List2, tempstring1);
  2310.  
  2311.             strcpy(tempstring1, "Paper type:             ");
  2312.             uvalue = getuword(&(contents[which].DataPtr[49]));
  2313.             if (uvalue == 0) // PT_FANFOLD
  2314.             {   strcat(tempstring1, "0 (fanfold)");
  2315.             } elif (uvalue == 1) // PP_SINGLE
  2316.             {   strcat(tempstring1, "1 (single sheet)");
  2317.             } else
  2318.             {   strcat(tempstring1, "?");
  2319.             }
  2320.             addreactionnode(&List2, tempstring1);
  2321.  
  2322.             strcpy(tempstring1, "Paper size:             ");
  2323.             uvalue = getuword(&(contents[which].DataPtr[51]));
  2324.             if (uvalue == 0) // PS_US_LETTER
  2325.             {   strcat(tempstring1, "0 (US Letter)");
  2326.             } elif (uvalue == 1) // PS_US_LEGAL
  2327.             {   strcat(tempstring1, "1 (US Legal)");
  2328.             } elif (uvalue == 2) // PS_N_TRACTOR
  2329.             {   strcat(tempstring1, "2 (narrow tractor)");
  2330.             } elif (uvalue == 3) // PS_W_TRACTOR
  2331.             {   strcat(tempstring1, "3 (wide tractor)");
  2332.             } elif (uvalue == 4) // PS_CUSTOM
  2333.             {   strcat(tempstring1, "4 (custom)");
  2334.             } elif (uvalue == 5) // PS_EURO_A0
  2335.             {   strcat(tempstring1, "5 (A0: 841x1189mm)");
  2336.             } elif (uvalue == 6) // PS_EURO_A1
  2337.             {   strcat(tempstring1, "6 (A1: 594x841mm)");
  2338.             } elif (uvalue == 7) // PS_EURO_A2
  2339.             {   strcat(tempstring1, "7 (A2: 420x594mm)");
  2340.             } elif (uvalue == 8) // PS_EURO_A3
  2341.             {   strcat(tempstring1, "8 (A3: 297x420mm)");
  2342.             } elif (uvalue == 9) // PS_EURO_A4
  2343.             {   strcat(tempstring1, "9 (A4: 210x297mm)");
  2344.             } elif (uvalue == 10) // PS_EURO_A5
  2345.             {   strcat(tempstring1, "10 (A5: 148x210mm)");
  2346.             } elif (uvalue == 11) // PS_EURO_A6
  2347.             {   strcat(tempstring1, "11 (A6: 105x148mm)");
  2348.             } elif (uvalue == 12) // PS_EURO_A7
  2349.             {   strcat(tempstring1, "12 (A7: 74x105mm)");
  2350.             } elif (uvalue == 13) // PS_EURO_A8
  2351.             {   strcat(tempstring1, "13 (A8: 52x74mm)");
  2352.             } else
  2353.             {   strcat(tempstring1, "?");
  2354.             }
  2355.             addreactionnode(&List2, tempstring1);
  2356.  
  2357.             strcpy(tempstring1, "Paper length:           ");
  2358.             uvalue = getuword(&(contents[which].DataPtr[53]));
  2359.             stcl_d(tempstring2, uvalue);
  2360.             strcat(tempstring1, tempstring2);
  2361.             strcat(tempstring1, " lines");
  2362.             addreactionnode(&List2, tempstring1);
  2363.  
  2364.             strcpy(tempstring1, "Pitch:                  ");
  2365.             uvalue = getuword(&(contents[which].DataPtr[55]));
  2366.             if (uvalue == 0) // PP_PICA
  2367.             {   strcat(tempstring1, "0 (pica)");
  2368.             } elif (uvalue == 1) // PP_ELITE
  2369.             {   strcat(tempstring1, "1 (elite)");
  2370.             } elif (uvalue == 2) // PP_FINE
  2371.             {   strcat(tempstring1, "2 (fine)");
  2372.             } else
  2373.             {   strcat(tempstring1, "?");
  2374.             }
  2375.             addreactionnode(&List2, tempstring1);
  2376.  
  2377.             strcpy(tempstring1, "Spacing:                ");
  2378.             uvalue = getuword(&(contents[which].DataPtr[57]));
  2379.             if (uvalue == 0) // PS_SIX_LPI
  2380.             {   strcat(tempstring1, "0 (6 lines per inch)");
  2381.             } elif (uvalue == 1) // PS_EIGHT_LPI
  2382.             {   strcat(tempstring1, "1 (8 lines per inch)");
  2383.             } else
  2384.             {   strcat(tempstring1, "?");
  2385.             }
  2386.             addreactionnode(&List2, tempstring1);
  2387.  
  2388.             strcpy(tempstring1, "Left margin:            ");
  2389.             uvalue = getuword(&(contents[which].DataPtr[59]));
  2390.             stcl_d(tempstring2, uvalue);
  2391.             strcat(tempstring1, tempstring2);
  2392.             addreactionnode(&List2, tempstring1);
  2393.  
  2394.             strcpy(tempstring1, "Right margin:           ");
  2395.             uvalue = getuword(&(contents[which].DataPtr[61]));
  2396.             stcl_d(tempstring2, uvalue);
  2397.             strcat(tempstring1, tempstring2);
  2398.             addreactionnode(&List2, tempstring1);
  2399.  
  2400.             strcpy(tempstring1, "Quality:                ");
  2401.             uvalue = getuword(&(contents[which].DataPtr[63]));
  2402.             if (uvalue == 0) // PQ_DRAFT
  2403.             {   strcat(tempstring1, "0 (draft)");
  2404.             } elif (uvalue == 1) // PQ_LETTER
  2405.             {   strcat(tempstring1, "1 (letter)");
  2406.             } else
  2407.             {   strcat(tempstring1, "?");
  2408.             }
  2409.             addreactionnode(&List2, tempstring1);
  2410.         }   }
  2411.         elif (!strcmp(contents[which].name, "SOND"))
  2412.         {   chunkdesc("Sound preferences", TRUE);
  2413.  
  2414.             // 16 reserved bytes at start
  2415.  
  2416.         if (!iff.raw)
  2417.         {
  2418.             strcpy(tempstring1, "Flash display?          ");
  2419.             uvalue = getuword(&contents[which].DataPtr[16]); // BOOL
  2420.             if (uvalue)
  2421.             {   strcat(tempstring1, "Yes");
  2422.             } else
  2423.             {   strcat(tempstring1, "No");
  2424.             }
  2425.             addreactionnode(&List2, tempstring1);
  2426.  
  2427.             strcpy(tempstring1, "Make sounds?            ");
  2428.             uvalue = getuword(&contents[which].DataPtr[18]); // BOOL
  2429.             if (uvalue)
  2430.             {   strcat(tempstring1, "Yes");
  2431.             } else
  2432.             {   strcat(tempstring1, "No");
  2433.             }
  2434.             addreactionnode(&List2, tempstring1);
  2435.  
  2436.             strcpy(tempstring1, "Type of sound:          ");
  2437.             uvalue = getuword(&contents[which].DataPtr[20]); // uword
  2438.             if (uvalue == 0) // SPTYPE_BEEP
  2439.             {   strcat(tempstring1, "Beep");
  2440.             } elif (uvalue == 1) // SPTYPE_SAMPLE
  2441.             {   strcat(tempstring1, "Sample");
  2442.             }
  2443.             addreactionnode(&List2, tempstring1);
  2444.  
  2445.             strcpy(tempstring1, "Volume:                 ");
  2446.             uvalue = getuword(&contents[which].DataPtr[22]); // uword
  2447.             stcl_d(tempstring2, uvalue);
  2448.             strcat(tempstring1, tempstring2);
  2449.             if (uvalue > 64)
  2450.             {   strcat(tempstring1, "!");
  2451.             }
  2452.             strcat(tempstring1, "/64");
  2453.             addreactionnode(&List2, tempstring1);
  2454.  
  2455.             strcpy(tempstring1, "Period:                 ");
  2456.             uvalue = getuword(&contents[which].DataPtr[24]); // uword
  2457.             stcl_d(tempstring2, uvalue);
  2458.             strcat(tempstring1, tempstring2);
  2459.             if (uvalue < 127 || uvalue > 2500)
  2460.             {   strcat(tempstring1, "!");
  2461.             }
  2462.             addreactionnode(&List2, tempstring1);
  2463.  
  2464.             strcpy(tempstring1, "Beep length:            ");
  2465.             uvalue = getuword(&contents[which].DataPtr[26]); // uword
  2466.             stcl_d(tempstring2, uvalue);
  2467.             strcat(tempstring1, tempstring2);
  2468.             addreactionnode(&List2, tempstring1);
  2469.  
  2470.             strcpy(tempstring1, "Sample filename:        ");
  2471.             strcat(tempstring1, &contents[which].DataPtr[28]); // 256 chars
  2472.             addreactionnode(&List2, tempstring1);
  2473.         }   }
  2474.         elif (!strcmp(contents[which].name, "PTRN"))
  2475.         {   chunkdesc("Workbench pattern preferences", TRUE);
  2476.  
  2477.             // 16 reserved bytes at start
  2478.  
  2479.         if (!iff.raw)
  2480.         {
  2481.             strcpy(tempstring1, "Which pattern?          ");
  2482.             uvalue = getuword(&contents[which].DataPtr[16]); // UWORD
  2483.             if (uvalue == 0) // WBP_ROOT
  2484.             {   strcat(tempstring1, "9 (Workbench)");
  2485.             } elif (uvalue == 1) // WBP_DRAWER
  2486.             {   strcat(tempstring1, "1 (window)");
  2487.             } elif (uvalue == 2) // WBP_SCREEN
  2488.             {   strcat(tempstring1, "2 (screen)");
  2489.             } else
  2490.             {   strcat(tempstring1, "?");
  2491.             }
  2492.             addreactionnode(&List2, tempstring1);
  2493.  
  2494.             uvalue = getuword(&contents[which].DataPtr[18]); // UWORD
  2495.  
  2496.             strcpy(tempstring1, "Data contains pattern?  ");
  2497.             if (uvalue & 1) // WBPF_PATTERN
  2498.             {   strcat(tempstring1, "Yes");
  2499.             } else
  2500.             {   strcat(tempstring1, "No");
  2501.             }
  2502.             addreactionnode(&List2, tempstring1);
  2503.  
  2504.             strcpy(tempstring1, "Remap pattern?          ");
  2505.             if (uvalue & 16) // WBPF_NOREMAP
  2506.             {   strcat(tempstring1, "No");
  2507.             } else
  2508.             {   strcat(tempstring1, "Yes");
  2509.             }
  2510.             addreactionnode(&List2, tempstring1);
  2511.  
  2512.             strcpy(tempstring1, "Dither quality:         ");
  2513.             if (uvalue & 768) // these comparisons are order-dependent
  2514.             {   strcat(tempstring1, "Best");
  2515.             } elif (uvalue & 512)
  2516.             {   strcat(tempstring1, "Good");
  2517.             } elif (uvalue & 256)
  2518.             {   strcat(tempstring1, "Poor");
  2519.             } else
  2520.             {   strcat(tempstring1, "Default");
  2521.             }
  2522.             addreactionnode(&List2, tempstring1);
  2523.  
  2524.             strcpy(tempstring1, "Colour quality:         ");
  2525.             if (uvalue & 3072) // these comparisons are order-dependent
  2526.             {   strcat(tempstring1, "Best");
  2527.             } elif (uvalue & 2048)
  2528.             {   strcat(tempstring1, "Good");
  2529.             } elif (uvalue & 1024)
  2530.             {   strcat(tempstring1, "Poor");
  2531.             } else
  2532.             {   strcat(tempstring1, "Default");
  2533.             }
  2534.             addreactionnode(&List2, tempstring1);
  2535.  
  2536.             strcpy(tempstring1, "Layout:                 ");
  2537.             if (uvalue & 12288) // these comparisons are order-dependent
  2538.             {   strcat(tempstring1, "Scale well");
  2539.             } elif (uvalue & 8192)
  2540.             {   strcat(tempstring1, "Scale");
  2541.             } elif (uvalue & 4096)
  2542.             {   strcat(tempstring1, "Centre");
  2543.             } else
  2544.             {   strcat(tempstring1, "Tile");
  2545.             }
  2546.             addreactionnode(&List2, tempstring1);
  2547.  
  2548.             strcpy(tempstring1, "Revision:               ");  // BYTE
  2549.             stcl_d(tempstring2, contents[which].DataPtr[20]);
  2550.             strcat(tempstring1, tempstring2);
  2551.             addreactionnode(&List2, tempstring1);
  2552.  
  2553.             strcpy(tempstring1, "Pattern depth:          ");  // BYTE
  2554.             stcl_d(tempstring2, contents[which].DataPtr[21]);
  2555.             strcat(tempstring1, tempstring2);
  2556.             addreactionnode(&List2, tempstring1);
  2557.  
  2558.             strcpy(tempstring1, "Data length:            ");  // UWORD
  2559.             uvalue = getuword(&contents[which].DataPtr[22]);
  2560.             stcl_d(tempstring2, uvalue);
  2561.             strcat(tempstring1, tempstring2);
  2562.             addreactionnode(&List2, tempstring1);
  2563.         }   }
  2564.         elif (!strcmp(contents[which].name, "PNTR"))
  2565.         {   chunkdesc("Pointer preferences", TRUE);
  2566.  
  2567.             // 16 reserved bytes at start
  2568.  
  2569.         if (!iff.raw)
  2570.         {
  2571.             strcpy(tempstring1, "Which pointer?          ");
  2572.             uvalue = getuword(&contents[which].DataPtr[16]); // UWORD
  2573.             if (uvalue == 0)
  2574.             {   strcat(tempstring1, "Normal");
  2575.             } elif (uvalue == 1)
  2576.             {   strcat(tempstring1, "Busy");
  2577.             } else
  2578.             {   strcat(tempstring1, "?");
  2579.             }
  2580.             addreactionnode(&List2, tempstring1);
  2581.  
  2582.             strcpy(tempstring1, "Horizontal size:        ");
  2583.             uvalue = getuword(&contents[which].DataPtr[18]); // UWORD
  2584.             if (uvalue == 0) // POINTERXRESN_DEFAULT
  2585.             {   strcat(tempstring1, "0 (default)");
  2586.             } elif (uvalue == 1) // POINTERXRESN_140NS
  2587.             {   strcat(tempstring1, "1 (140ns)");
  2588.             } elif (uvalue == 2) // POINTERXRESN_70NS
  2589.             {   strcat(tempstring1, "2 (70ns)");
  2590.             } elif (uvalue == 3) // POINTERXRESN_35NS
  2591.             {   strcat(tempstring1, "3 (35ns)");
  2592.             } elif (uvalue == 4) // POINTERXRESN_SCREENRES
  2593.             {   strcat(tempstring1, "4 (screen)");
  2594.             } elif (uvalue == 5) // POINTERXRESN_LORES
  2595.             {   strcat(tempstring1, "5 (low resolution)");
  2596.             } elif (uvalue == 6) // POINTERXRESN_HIRES
  2597.             {   strcat(tempstring1, "6 (high resolution)");
  2598.             } else
  2599.             {   strcat(tempstring1, "?");
  2600.             }
  2601.             addreactionnode(&List2, tempstring1);
  2602.  
  2603.             stcl_d(tempstring2, uvalue);
  2604.             strcat(tempstring1, tempstring2);
  2605.             addreactionnode(&List2, tempstring1);
  2606.  
  2607.             strcpy(tempstring1, "Width:                  ");
  2608.             uvalue = getuword(&contents[which].DataPtr[20]); // UWORD
  2609.             stcl_d(tempstring2, uvalue);
  2610.             strcat(tempstring1, tempstring2);
  2611.             strcat(tempstring1, " pixels");
  2612.             addreactionnode(&List2, tempstring1);
  2613.  
  2614.             strcpy(tempstring1, "Height:                 ");
  2615.             uvalue = getuword(&contents[which].DataPtr[22]); // UWORD
  2616.             stcl_d(tempstring2, uvalue);
  2617.             strcat(tempstring1, tempstring2);
  2618.             strcat(tempstring1, " pixels");
  2619.             addreactionnode(&List2, tempstring1);
  2620.  
  2621.             strcpy(tempstring1, "Depth:                  ");
  2622.             uvalue = getuword(&contents[which].DataPtr[24]); // UWORD
  2623.             stcl_d(tempstring2, uvalue);
  2624.             strcat(tempstring1, tempstring2);
  2625.             strcat(tempstring1, " planes");
  2626.             addreactionnode(&List2, tempstring1);
  2627.  
  2628.             strcpy(tempstring1, "Vertical size:          ");
  2629.             uvalue = getuword(&contents[which].DataPtr[26]); // UWORD
  2630.             if (uvalue == 0) // POINTERYRESN_DEFAULT
  2631.             {   strcat(tempstring1, "0 (default)");
  2632.             } elif (uvalue == 1) // POINTERYRESN_HIGH
  2633.             {   strcat(tempstring1, "1 (high non-aspect)");
  2634.             } elif (uvalue == 2) // POINTERYRESN_HIGHASPECT
  2635.             {   strcat(tempstring1, "2 (high aspect)");
  2636.             } elif (uvalue == 3) // POINTERYRESN_SCREENRES
  2637.             {   strcat(tempstring1, "3 (screen non-aspect)");
  2638.             } elif (uvalue == 4) // POINTERYRESN_SCREENRESASPECT
  2639.             {   strcat(tempstring1, "4 (screen aspect)");
  2640.             } else
  2641.             {   strcat(tempstring1, "?");
  2642.             }
  2643.             addreactionnode(&List2, tempstring1);
  2644.  
  2645.             strcpy(tempstring1, "Hotspot coordinates:    ");
  2646.             uvalue = getuword(&contents[which].DataPtr[28]); // UWORD
  2647.             stcl_d(tempstring2, uvalue);
  2648.             strcat(tempstring1, tempstring2);
  2649.             strcat(tempstring1, ",");
  2650.             uvalue = getuword(&contents[which].DataPtr[30]); // UWORD
  2651.             stcl_d(tempstring2, uvalue);
  2652.             strcat(tempstring1, tempstring2);
  2653.             addreactionnode(&List2, tempstring1);
  2654.         }   }
  2655.         elif (!strcmp(contents[which].name, "PALT")) // ignored
  2656.         {   chunkdesc("Palette preferences", FALSE);
  2657.         } elif (!strcmp(contents[which].name, "AHIG"))
  2658.         {   chunkdesc("AHI global preferences", TRUE);
  2659.  
  2660.             if (!iff.raw)
  2661.             {   strcpy(tempstring1, "Debug level:            ");
  2662.                 uvalue = getuword(contents[which].DataPtr); // UWORD
  2663.                 stcl_d(tempstring2, uvalue);
  2664.                 strcat(tempstring1, tempstring2);
  2665.                 if (uvalue == 0)
  2666.                 {   strcat(tempstring1, " (none)");
  2667.                 } elif (uvalue == 1)
  2668.                 {   strcat(tempstring1, " (low)");
  2669.                 } elif (uvalue == 2)
  2670.                 {   strcat(tempstring1, " (high)");
  2671.                 } elif (uvalue == 3)
  2672.                 {   strcat(tempstring1, " (all)");
  2673.                 } else
  2674.                 {   strcat(tempstring1, " (?)");
  2675.                 }
  2676.                 addreactionnode(&List2, tempstring1);
  2677.  
  2678.                 strcpy(tempstring1, "Disable surround sound? ");
  2679.                 uvalue = getuword(&contents[which].DataPtr[2]); // BOOL
  2680.                 if (uvalue)
  2681.                 {   strcat(tempstring1, "Yes");
  2682.                 } else
  2683.                 {   strcat(tempstring1, "No");
  2684.                 }
  2685.                 addreactionnode(&List2, tempstring1);
  2686.  
  2687.                 strcpy(tempstring1, "Disable echo?           ");
  2688.                 uvalue = getuword(&contents[which].DataPtr[4]); // BOOL
  2689.                 if (uvalue)
  2690.                 {   strcat(tempstring1, "Yes");
  2691.                 } else
  2692.                 {   strcat(tempstring1, "No");
  2693.                 }
  2694.                 addreactionnode(&List2, tempstring1);
  2695.  
  2696.                 strcpy(tempstring1, "Fast echo?              ");
  2697.                 uvalue = getuword(&contents[which].DataPtr[6]); // BOOL
  2698.                 if (uvalue)
  2699.                 {   strcat(tempstring1, "Yes");
  2700.                 } else
  2701.                 {   strcat(tempstring1, "No");
  2702.                 }
  2703.                 addreactionnode(&List2, tempstring1);
  2704.  
  2705.                 strcpy(tempstring1, "Maximum CPU usage:      ");
  2706.                 svalue = getslong(&(contents[which].DataPtr[8]));
  2707.                 svalue /= 1024; // LONG (Fixed)
  2708.                 stcl_d(tempstring2, svalue);
  2709.                 strcat(tempstring1, tempstring2);
  2710.                 strcat(tempstring1, "/64");
  2711.                 addreactionnode(&List2, tempstring1);
  2712.  
  2713.                 strcpy(tempstring1, "Clip master volume?     ");
  2714.                 uvalue = getuword(&contents[which].DataPtr[12]); // BOOL
  2715.                 if (uvalue)
  2716.                 {   strcat(tempstring1, "Yes");
  2717.                 } else
  2718.                 {   strcat(tempstring1, "No");
  2719.                 }
  2720.                 addreactionnode(&List2, tempstring1);
  2721.         }   }
  2722.         elif (!strcmp(contents[which].name, "AHIU"))
  2723.         {   chunkdesc("AHI unit preferences", TRUE);
  2724.  
  2725.             if (!iff.raw)
  2726.             {   strcpy(tempstring1, "Unit:                   ");
  2727.                 stcl_d(tempstring2, contents[which].DataPtr[0]); // UBYTE
  2728.                 strcat(tempstring1, tempstring2);
  2729.                 addreactionnode(&List2, tempstring1);
  2730.  
  2731.                 // byte 1 is a pad byte
  2732.  
  2733.                 strcpy(tempstring1, "Channels:               ");
  2734.                 uvalue = getuword(&contents[which].DataPtr[2]); // UWORD
  2735.                 stcl_d(tempstring2, uvalue);
  2736.                 strcat(tempstring1, tempstring2);
  2737.                 addreactionnode(&List2, tempstring1);
  2738.  
  2739.                 strcpy(tempstring1, "Audio mode:             ");
  2740.                 uvalue = getuword(&contents[which].DataPtr[4]); // ULONG
  2741.                 stcl_d(tempstring2, uvalue);
  2742.                 strcat(tempstring1, tempstring2);
  2743.                 addreactionnode(&List2, tempstring1); // perhaps this can be interpreted?
  2744.  
  2745.                 strcpy(tempstring1, "Frequency:              ");
  2746.                 uvalue = getuword(&contents[which].DataPtr[8]); // ULONG
  2747.                 stcl_d(tempstring2, uvalue);
  2748.                 strcat(tempstring1, tempstring2);
  2749.                 addreactionnode(&List2, tempstring1);
  2750.  
  2751.                 strcpy(tempstring1, "Monitor volume:         ");
  2752.                 svalue = getslong(&(contents[which].DataPtr[12]));
  2753.                 svalue /= 1024; // LONG (Fixed)
  2754.                 stcl_d(tempstring2, svalue);
  2755.                 strcat(tempstring1, tempstring2);
  2756.                 strcat(tempstring1, "/64");
  2757.                 addreactionnode(&List2, tempstring1);
  2758.  
  2759.                 strcpy(tempstring1, "Input gain:             ");
  2760.                 svalue = getslong(&(contents[which].DataPtr[16]));
  2761.                 svalue /= 1024; // LONG (Fixed)
  2762.                 stcl_d(tempstring2, svalue);
  2763.                 strcat(tempstring1, tempstring2);
  2764.                 strcat(tempstring1, "/64");
  2765.                 addreactionnode(&List2, tempstring1);
  2766.  
  2767.                 strcpy(tempstring1, "Output volume:          ");
  2768.                 svalue = getslong(&(contents[which].DataPtr[20]));
  2769.                 svalue /= 1024; // LONG (Fixed)
  2770.                 stcl_d(tempstring2, svalue);
  2771.                 strcat(tempstring1, tempstring2);
  2772.                 strcat(tempstring1, "/64");
  2773.                 addreactionnode(&List2, tempstring1);
  2774.  
  2775.                 strcpy(tempstring1, "Input:                  ");
  2776.                 uvalue = getuword(&contents[which].DataPtr[24]); // ULONG
  2777.                 stcl_d(tempstring2, uvalue);
  2778.                 strcat(tempstring1, tempstring2);
  2779.                 addreactionnode(&List2, tempstring1); // perhaps this can be interpreted?
  2780.  
  2781.                 strcpy(tempstring1, "Output:                 ");
  2782.                 uvalue = getuword(&contents[which].DataPtr[28]); // ULONG
  2783.                 stcl_d(tempstring2, uvalue);
  2784.                 strcat(tempstring1, tempstring2);
  2785.                 addreactionnode(&List2, tempstring1); // perhaps this can be interpreted?
  2786.         }   }
  2787.         elif (!strcmp(contents[which].name, "WBNC"))
  2788.         {   chunkdesc("Workbench preferences", TRUE);
  2789.  
  2790.         if (!iff.raw)
  2791.         {
  2792.             strcpy(tempstring1, "Default stack size:     ");
  2793.             uvalue = getulong(contents[which].DataPtr); // ULONG
  2794.             stcl_d(tempstring2, uvalue);
  2795.             strcat(tempstring1, tempstring2);
  2796.             strcat(tempstring1, " bytes");
  2797.             addreactionnode(&List2, tempstring1);
  2798.  
  2799.             strcpy(tempstring1, "Type restart time:      ");
  2800.             uvalue = getulong(&contents[which].DataPtr[4]); // ULONG
  2801.             stcl_d(tempstring2, uvalue);
  2802.             strcat(tempstring1, tempstring2);
  2803.             strcat(tempstring1, " seconds");
  2804.             addreactionnode(&List2, tempstring1);
  2805.  
  2806.             strcpy(tempstring1, "Icon precision:         ");
  2807.             uvalue = getulong(&contents[which].DataPtr[8]); // ULONG
  2808.             if (uvalue == (ULONG) -1) // PRECISION_EXACT
  2809.             {   strcat(tempstring1, "-1 (exact)");
  2810.             } elif (uvalue == 0) // PRECISION_IMAGE
  2811.             {   strcat(tempstring1, "0 (image)");
  2812.             } elif (uvalue == 16) // PRECISION_ICON
  2813.             {   strcat(tempstring1, "16 (icon)");
  2814.             } elif (uvalue == 32) // PRECISION_GUI
  2815.             {   strcat(tempstring1, "32 (GUI)");
  2816.             } else
  2817.             {   strcat(tempstring1, "?");
  2818.             }
  2819.             addreactionnode(&List2, tempstring1);
  2820.  
  2821.             strcpy(tempstring1, "Emboss rectangle:       ");
  2822.  
  2823.             strcpy(tempstring1, " Top-left corner:       ");
  2824.             svalue = getsword(&contents[which].DataPtr[12]); // WORD
  2825.             stcl_d(tempstring2, svalue);
  2826.             strcat(tempstring1, tempstring2);
  2827.             strcat(tempstring1, ",");
  2828.             svalue = getuword(&contents[which].DataPtr[14]); // WORD
  2829.             stcl_d(tempstring2, svalue);
  2830.             strcat(tempstring1, tempstring2);
  2831.             addreactionnode(&List2, tempstring1);
  2832.  
  2833.             strcpy(tempstring1, " Bottom-right corner:   ");
  2834.             svalue = getsword(&contents[which].DataPtr[16]); // WORD
  2835.             stcl_d(tempstring2, svalue);
  2836.             strcat(tempstring1, tempstring2);
  2837.             strcat(tempstring1, ",");
  2838.             svalue = getuword(&contents[which].DataPtr[18]); // WORD
  2839.             stcl_d(tempstring2, svalue);
  2840.             strcat(tempstring1, tempstring2);
  2841.             addreactionnode(&List2, tempstring1);
  2842.  
  2843.             strcpy(tempstring1, "Borderless?             ");
  2844.             uvalue = getuword(&contents[which].DataPtr[20]); // BOOL
  2845.             if (uvalue)
  2846.             {   strcat(tempstring1, "Yes");
  2847.             } else
  2848.             {   strcat(tempstring1, "No");
  2849.             }
  2850.             addreactionnode(&List2, tempstring1);
  2851.  
  2852.             strcpy(tempstring1, "Max. filename length:   ");
  2853.             svalue = getslong(&contents[which].DataPtr[22]); // LONG
  2854.             stcl_d(tempstring2, svalue);
  2855.             strcat(tempstring1, tempstring2);
  2856.             strcat(tempstring1, " characters");
  2857.             addreactionnode(&List2, tempstring1);
  2858.  
  2859.             strcpy(tempstring1, "NewIcons support?       ");
  2860.             uvalue = getuword(&contents[which].DataPtr[26]); // BOOL
  2861.             if (uvalue)
  2862.             {   strcat(tempstring1, "Yes");
  2863.             } else
  2864.             {   strcat(tempstring1, "No");
  2865.             }
  2866.             addreactionnode(&List2, tempstring1);
  2867.  
  2868.             strcpy(tempstring1, "ColourIcons support?    ");
  2869.             uvalue = getuword(&contents[which].DataPtr[28]); // BOOL
  2870.             if (uvalue)
  2871.             {   strcat(tempstring1, "Yes");
  2872.             } else
  2873.             {   strcat(tempstring1, "No");
  2874.             }
  2875.             addreactionnode(&List2, tempstring1);
  2876.  
  2877.             // remainder of these are new for OS3.9
  2878.  
  2879.             if (contents[which].bytes > 30)
  2880.             {   strcpy(tempstring1, "Image memory type:      ");
  2881.                 uvalue = getulong(&contents[which].DataPtr[30]); // ULONG
  2882.                 if (uvalue == 1)
  2883.                 {   strcat(tempstring1, "Other memory");
  2884.                 } elif (uvalue == 2)
  2885.                 {   strcat(tempstring1, "Graphics (chip) memory");
  2886.                 } else
  2887.                 {   strcat(tempstring1, "?");
  2888.                 }
  2889.                 addreactionnode(&List2, tempstring1);
  2890.  
  2891.                 strcpy(tempstring1, "Lock pens?              ");
  2892.                 uvalue = getuword(&contents[which].DataPtr[34]); // BOOL
  2893.                 if (uvalue)
  2894.                 {   strcat(tempstring1, "Yes");
  2895.                 } else
  2896.                 {   strcat(tempstring1, "No");
  2897.                 }
  2898.                 addreactionnode(&List2, tempstring1);
  2899.  
  2900.                 strcpy(tempstring1, "Title bar?              "); // this is inverted
  2901.                 uvalue = getuword(&contents[which].DataPtr[36]); // BOOL
  2902.                 if (uvalue)
  2903.                 {   strcat(tempstring1, "No");
  2904.                 } else
  2905.                 {   strcat(tempstring1, "Yes");
  2906.                 }
  2907.                 addreactionnode(&List2, tempstring1);
  2908.  
  2909.                 strcpy(tempstring1, "Volume gauge?           "); // this is inverted
  2910.                 uvalue = getuword(&contents[which].DataPtr[38]); // BOOL
  2911.                 if (uvalue)
  2912.                 {   strcat(tempstring1, "No");
  2913.                 } else
  2914.                 {   strcat(tempstring1, "Yes");
  2915.                 }
  2916.                 addreactionnode(&List2, tempstring1);
  2917.         }   }   }
  2918.         elif (!strcmp(contents[which].name, "WBHD"))
  2919.         {   chunkdesc("Workbench hidden device preferences", TRUE);
  2920.  
  2921.             if (!iff.raw)
  2922.             {   strcpy(tempstring1, "Name:                   ");
  2923.                 strcat(tempstring1, contents[which].DataPtr);
  2924.                 addreactionnode(&List2, tempstring1);
  2925.         }   }
  2926.         elif (!strcmp(contents[which].name, "LCLE"))
  2927.         {   chunkdesc("Locale preferences", TRUE);
  2928.  
  2929.             // 16 reserved bytes at start
  2930.  
  2931.         if (!iff.raw)
  2932.         {   strcpy(tempstring1, "Country name:           ");
  2933.             strcat(tempstring1, &contents[which].DataPtr[16]); // 32 chars
  2934.             addreactionnode(&List2, tempstring1);
  2935.  
  2936.             strcpy(tempstring1, "Preferred languages:    ");
  2937.             addreactionnode(&List2, tempstring1);
  2938.  
  2939.             for (i = 1; i <= 10; i++)
  2940.             {   strcpy(tempstring1, " ");
  2941.                 if (i < 10)
  2942.                 {   strcat(tempstring1, " ");
  2943.                 }
  2944.                 stcl_d(tempstring2, i);
  2945.                 strcat(tempstring1, tempstring2);
  2946.                 strcat(tempstring1, ":                    ");
  2947.                 strcat(tempstring1, &contents[which].DataPtr[48 + ((i - 1) * 30)]); // 10 entries of 30 chars each
  2948.                 addreactionnode(&List2, tempstring1);
  2949.             }
  2950.  
  2951.             strcpy(tempstring1, "Time from GMT:          ");
  2952.             svalue = getslong(&contents[which].DataPtr[348]); // LONG
  2953.             stcl_d(tempstring2, svalue);
  2954.             strcat(tempstring1, tempstring2);
  2955.             strcat(tempstring1, " minutes");
  2956.             addreactionnode(&List2, tempstring1);
  2957.  
  2958.             strcpy(tempstring1, "Flags:                  ");
  2959.             uvalue = getulong(&contents[which].DataPtr[352]); // ULONG
  2960.             stcl_d(tempstring2, uvalue);
  2961.             strcat(tempstring1, tempstring2);
  2962.             addreactionnode(&List2, tempstring1);
  2963.  
  2964.             docountry(&contents[which].DataPtr[356]);
  2965.         }   }
  2966.         elif (!strcmp(contents[which].name, "CTRY"))
  2967.         {   chunkdesc("Country preferences", TRUE);
  2968.  
  2969.             if (!iff.raw)
  2970.             {   docountry(contents[which].DataPtr);
  2971.         }   }
  2972.         elif (!strcmp(contents[which].name, "RACT"))
  2973.         {   chunkdesc("ReAction preferences", TRUE);
  2974.  
  2975.         if (!iff.raw)
  2976.         {
  2977.             strcpy(tempstring1, "Bevel type:             "); // UWORD
  2978.             uvalue = getuword(contents[which].DataPtr);
  2979.             if (uvalue == 0) // BVT_GT
  2980.             {   strcat(tempstring1, "0 (GadTools 2:1)");
  2981.             } elif (uvalue == 1) // BVT_THIN
  2982.             {   strcat(tempstring1, "1 (ReAction 1:1)");
  2983.             } elif (uvalue == 2) // BVT_THICK
  2984.             {   strcat(tempstring1, "2 (ReAction 2:1)");
  2985.             } elif (uvalue == 3) // BVT_THIN
  2986.             {   strcat(tempstring1, "3 (XEN 2:1)");
  2987.             } elif (uvalue == 4) // BVT_THIN
  2988.             {   strcat(tempstring1, "4 (XEN 1:1)");
  2989.             } else
  2990.             {   strcat(tempstring1, "?");
  2991.             }
  2992.             addreactionnode(&List2, tempstring1);
  2993.  
  2994.             strcpy(tempstring1, "Glyph type:             "); // UWORD
  2995.             uvalue = getuword(&contents[which].DataPtr[2]);
  2996.             if (uvalue == 0) // GLT_GT
  2997.             {   strcat(tempstring1, "0 (GadTools)");
  2998.             } elif (uvalue == 1) // GLT_FLAT
  2999.             {   strcat(tempstring1, "1 (Flat)");
  3000.             } elif (uvalue == 2) // GLT_3D
  3001.             {   strcat(tempstring1, "2 (3D)");
  3002.             } else
  3003.             {   strcat(tempstring1, "?");
  3004.             }
  3005.             addreactionnode(&List2, tempstring1);
  3006.  
  3007.             strcpy(tempstring1, "Layout spacing:         "); // UWORD
  3008.             uvalue = getuword(&contents[which].DataPtr[4]);
  3009.             stcl_d(tempstring2, uvalue);
  3010.             strcat(tempstring1, tempstring2);
  3011.             addreactionnode(&List2, tempstring1);
  3012.  
  3013.             strcpy(tempstring1, "3D Proportional?        ");
  3014.             uvalue = getuword(&contents[which].DataPtr[6]); // BOOL
  3015.             if (uvalue)
  3016.             {   strcat(tempstring1, "Yes");
  3017.             } else
  3018.             {   strcat(tempstring1, "No");
  3019.             }
  3020.             addreactionnode(&List2, tempstring1);
  3021.  
  3022.             strcpy(tempstring1, "Label pen:              "); // UWORD
  3023.             uvalue = getuword(&contents[which].DataPtr[8]);
  3024.             stcl_d(tempstring2, uvalue);
  3025.             strcat(tempstring1, tempstring2);
  3026.             addreactionnode(&List2, tempstring1);
  3027.  
  3028.             strcpy(tempstring1, "Label placement:        "); // UWORD
  3029.             uvalue = getuword(&contents[which].DataPtr[10]);
  3030.             /* This has been reverse-engineered
  3031.             using the ReAction preferences editor */
  3032.             if (uvalue == 0)
  3033.             {   strcat(tempstring1, "0 (centre)");
  3034.             } elif (uvalue == 1)
  3035.             {   strcat(tempstring1, "1 (left)");
  3036.             } elif (uvalue == 2)
  3037.             {   strcat(tempstring1, "2 (right)");
  3038.             }
  3039.             addreactionnode(&List2, tempstring1);
  3040.  
  3041.             strcpy(tempstring1, "3D Label?               ");
  3042.             uvalue = getuword(&contents[which].DataPtr[12]); // BOOL
  3043.             if (uvalue)
  3044.             {   strcat(tempstring1, "Yes");
  3045.             } else
  3046.             {   strcat(tempstring1, "No");
  3047.             }
  3048.             addreactionnode(&List2, tempstring1);
  3049.  
  3050.             strcpy(tempstring1, "Refreshing Method:      ");
  3051.             uvalue = getuword(&contents[which].DataPtr[14]); // BOOL
  3052.             if (uvalue)
  3053.             {   strcat(tempstring1, "Simple");
  3054.             } else
  3055.             {   strcat(tempstring1, "Smart");
  3056.             }
  3057.             addreactionnode(&List2, tempstring1);
  3058.  
  3059.             strcpy(tempstring1, "3D Look?                ");
  3060.             uvalue = getuword(&contents[which].DataPtr[16]); // BOOL
  3061.             if (uvalue)
  3062.             {   strcat(tempstring1, "Yes");
  3063.             } else
  3064.             {   strcat(tempstring1, "No");
  3065.             }
  3066.             addreactionnode(&List2, tempstring1);
  3067.  
  3068.             addreactionnode(&List2, "Fallback font:");
  3069.             dotextattr(&contents[which].DataPtr[18]); // struct TextAttr (8 bytes)
  3070.             addreactionnode(&List2, "Label font:");
  3071.             dotextattr(&contents[which].DataPtr[26]); // struct TextAttr (8 bytes)
  3072.  
  3073.             strcpy(tempstring1, "Fallback font name:     ");
  3074.             strcat(tempstring1, &contents[which].DataPtr[34]); // 128 UBYTEs
  3075.             addreactionnode(&List2, tempstring1);
  3076.  
  3077.             strcpy(tempstring1, "Label font name:        ");
  3078.             strcat(tempstring1, &contents[which].DataPtr[162]); // 128 UBYTEs
  3079.             addreactionnode(&List2, tempstring1);
  3080.  
  3081.             strcpy(tempstring1, "Backdrop pattern:       ");
  3082.             strcat(tempstring1, &contents[which].DataPtr[290]); // 256 UBYTEs
  3083.             addreactionnode(&List2, tempstring1);
  3084.         }   }
  3085.         elif (!strcmp(contents[which].name, "PRHD"))
  3086.         {   chunkdesc("Preferences header", TRUE);
  3087.  
  3088.         if (!iff.raw)
  3089.         {
  3090.             strcpy(tempstring1, "Version:                ");
  3091.             stcl_d(tempstring2, contents[which].DataPtr[0]);
  3092.             strcat(tempstring1, tempstring2);
  3093.             addreactionnode(&List2, tempstring1);
  3094.                                
  3095.             strcpy(tempstring1, "Type:                   ");
  3096.             stcl_d(tempstring2, contents[which].DataPtr[1]);
  3097.             strcat(tempstring1, tempstring2);
  3098.             addreactionnode(&List2, tempstring1);
  3099.  
  3100.             strcpy(tempstring1, "Flags:                  ");
  3101.             uvalue = getuword(&(contents[which].DataPtr[2]));
  3102.             stcl_d(tempstring2, uvalue);
  3103.             strcat(tempstring1, tempstring2);
  3104.             addreactionnode(&List2, tempstring1);
  3105.     }   }   }
  3106.     elif (!strcmp(queryform, "SMUS"))
  3107.     {   if (!strcmp(contents[which].name, "SHDR"))
  3108.         {   chunkdesc("Global information for the score", TRUE);
  3109.  
  3110.         if (!iff.raw)
  3111.         {
  3112.             strcpy(tempstring1, "Tempo:              ");
  3113.             uvalue = getuword(contents[which].DataPtr);
  3114.             uvalue = uvalue / 128;
  3115.             stcl_d(tempstring2, uvalue);
  3116.             strcat(tempstring1, tempstring2);
  3117.             strcat(tempstring1, " bpm");
  3118.             addreactionnode(&List2, tempstring1);
  3119.  
  3120.             strcpy(tempstring1, "Volume:             ");
  3121.             uvalue = contents[which].DataPtr[2];
  3122.             stcl_d(tempstring2, uvalue);
  3123.             strcat(tempstring1, tempstring2);
  3124.             strcat(tempstring1, "/127");
  3125.             addreactionnode(&List2, tempstring1);
  3126.  
  3127.             strcpy(tempstring1, "Tracks:             ");
  3128.             uvalue = contents[which].DataPtr[3];
  3129.             stcl_d(tempstring2, uvalue);
  3130.             strcat(tempstring1, tempstring2);
  3131.             addreactionnode(&List2, tempstring1);
  3132.         }   }
  3133.         elif (!strcmp(contents[which].name, "INS1"))
  3134.         {   chunkdesc("Identifies an instrument to use", TRUE);
  3135.  
  3136.         if (!iff.raw)
  3137.         {
  3138.             strcpy(tempstring1, "Register number:    ");
  3139.             stcl_d(tempstring2, contents[which].DataPtr[0]); // UBYTE
  3140.             strcat(tempstring1, tempstring2);
  3141.             addreactionnode(&List2, tempstring1);
  3142.  
  3143.             strcpy(tempstring1, "Reference type:     ");
  3144.             if (contents[which].DataPtr[1] == 0) // UBYTE
  3145.             {   strcat(tempstring1, "Find by name");
  3146.             } elif (contents[which].DataPtr[1] == 1)
  3147.             {   strcat(tempstring1, "Find on MIDI");
  3148.             } else strcat(tempstring1, "?");
  3149.             addreactionnode(&List2, tempstring1);
  3150.  
  3151.             strcpy(tempstring1, "MIDI channel:       ");
  3152.             if (contents[which].DataPtr[1] == 1) // if find on MIDI
  3153.             {   stcl_d(tempstring2, contents[which].DataPtr[2]); // UBYTE
  3154.                 strcat(tempstring1, tempstring2);
  3155.             } else strcat(tempstring1, "n/a");
  3156.             addreactionnode(&List2, tempstring1);
  3157.  
  3158.             strcpy(tempstring1, "MIDI preset:        ");
  3159.             if (contents[which].DataPtr[1] == 1) // if find on MIDI
  3160.             {   stcl_d(tempstring2, contents[which].DataPtr[3]); // UBYTE
  3161.                 strcat(tempstring1, tempstring2);
  3162.             } else strcat(tempstring1, "n/a");
  3163.             addreactionnode(&List2, tempstring1);
  3164.  
  3165.             strcpy(tempstring1, "Instrument name:    ");
  3166.             strcat(tempstring1, (STRPTR) contents[which].DataPtr + 4); // STRPTR
  3167.             addreactionnode(&List2, tempstring1);
  3168.         }   }
  3169.         elif (!strcmp(contents[which].name, "TRAK"))
  3170.         {   chunkdesc("Linear stream of events", FALSE);
  3171.         } elif (!strcmp(contents[which].name, "INST"))
  3172.         {   chunkdesc("Obsolete; use INS1 instead", FALSE);
  3173.         } elif (!stricmp(contents[which].name, "IRev")) // this could also perhaps be IREV
  3174.         {   chunkdesc("Instant Music private chunk", FALSE);
  3175.         } elif (!strcmp(contents[which].name, "BIAS"))
  3176.         {   chunkdesc("Instant Music private chunk", FALSE);
  3177.     }   }
  3178.     elif (!strcmp(queryform, "HEAD"))
  3179.     {   if (!strcmp(contents[which].name, "NEST"))
  3180.         {   chunkdesc("Nesting level", TRUE);
  3181.  
  3182.             if (!iff.raw)
  3183.             {   strcpy(tempstring1, "Nesting level:      ");
  3184.                 uvalue = getuword(contents[which].DataPtr);
  3185.                 stcl_d(tempstring2, uvalue);
  3186.                 strcat(tempstring1, tempstring2);
  3187.                 addreactionnode(&List2, tempstring1);
  3188.         }   }
  3189.         elif (!strcmp(contents[which].name, "TEXT"))
  3190.         {   chunkdesc("Heading text", FALSE);
  3191.     }   }
  3192.     elif (!strcmp(queryform, "WORD"))
  3193.     {   if (!strcmp(contents[which].name, "FONT"))
  3194.         {   chunkdesc("Font name/number table", TRUE);
  3195.  
  3196.         if (!iff.raw)
  3197.         {
  3198.             strcpy(tempstring1, "Number:             ");
  3199.             uvalue = contents[which].DataPtr[0]; // UBYTE
  3200.             stcl_d(tempstring2, uvalue);
  3201.             strcat(tempstring1, tempstring2);
  3202.             addreactionnode(&List2, tempstring1);
  3203.  
  3204.             strcpy(tempstring1, "Size:               ");
  3205.             uvalue = getuword(&contents[which].DataPtr[1]);
  3206.             stcl_d(tempstring2, uvalue);
  3207.             strcat(tempstring1, tempstring2);
  3208.             addreactionnode(&List2, tempstring1);
  3209.  
  3210.             strcpy(tempstring1, "Name:               ");
  3211.             strcat(tempstring1, &contents[which].DataPtr[3]);
  3212.             addreactionnode(&List2, tempstring1);
  3213.         }   }
  3214.         elif (!strcmp(contents[which].name, "COLR"))
  3215.         {   chunkdesc("Colour translation table", TRUE);
  3216.  
  3217.             if (!iff.raw)
  3218.             {   for (i = 0; i <= 7; i++)
  3219.                 {   strcpy(tempstring1, "Colour ");
  3220.                     stcl_d(tempstring2, i);
  3221.                     strcat(tempstring1, tempstring2);
  3222.                     strcat(tempstring1, ":           ");
  3223.                     uvalue = contents[which].DataPtr[i]; // UBYTE
  3224.                     stcl_d(tempstring2, uvalue);
  3225.                     strcat(tempstring1, tempstring2);
  3226.                     addreactionnode(&List2, tempstring1);
  3227.         }   }   }
  3228.         elif (!strcmp(contents[which].name, "DOC "))
  3229.         {   chunkdesc("Begin document section", TRUE);
  3230.  
  3231.             if (!iff.raw)
  3232.             {   strcpy(tempstring1, "Starting page:      ");
  3233.                 uvalue = getuword(contents[which].DataPtr);
  3234.                 stcl_d(tempstring2, uvalue);
  3235.                 strcat(tempstring1, tempstring2);
  3236.                 addreactionnode(&List2, tempstring1);
  3237.  
  3238.                 strcpy(tempstring1, "Numbering style:    ");
  3239.                 if (contents[which].DataPtr[2] == 0)
  3240.                 {   strcat(tempstring1, "1, 2, 3...");
  3241.                 } elif (contents[which].DataPtr[2] == 1)
  3242.                 {   strcat(tempstring1, "I, II, III...");
  3243.                 } elif (contents[which].DataPtr[2] == 2)
  3244.                 {   strcat(tempstring1, "i, ii, iii...");
  3245.                 } elif (contents[which].DataPtr[2] == 3)
  3246.                 {   strcat(tempstring1, "A, B, C...");
  3247.                 } elif (contents[which].DataPtr[2] == 4)
  3248.                 {   strcat(tempstring1, "a, b, c...");
  3249.                 } else
  3250.                 {   strcat(tempstring1, "?");
  3251.                 }
  3252.                 addreactionnode(&List2, tempstring1);
  3253.         }   }
  3254.         elif (!strcmp(contents[which].name, "HEAD"))
  3255.         {   chunkdesc("Begin header section", TRUE);
  3256.  
  3257.             if (!iff.raw)
  3258.             {   strcpy(tempstring1, "Page type:           ");
  3259.                 if (contents[which].DataPtr[0] == 0)
  3260.                 {   strcat(tempstring1, "None");
  3261.                 } elif (contents[which].DataPtr[0] == 1)
  3262.                 {   strcat(tempstring1, "Left");
  3263.                 } elif (contents[which].DataPtr[0] == 2)
  3264.                 {   strcat(tempstring1, "Right");
  3265.                 } elif (contents[which].DataPtr[0] == 3)
  3266.                 {   strcat(tempstring1, "Both");
  3267.                 } else strcat(tempstring1, "?");
  3268.                 addreactionnode(&List2, tempstring1);
  3269.  
  3270.                 strcpy(tempstring1, "First page?          ");
  3271.                 if (contents[which].DataPtr[1] == 0)
  3272.                 {   strcat(tempstring1, "No");
  3273.                 } else strcat(tempstring1, "Yes");
  3274.                 addreactionnode(&List2, tempstring1);
  3275.         }   }
  3276.         elif (!strcmp(contents[which].name, "FOOT"))
  3277.         {   chunkdesc("Begin footer section", TRUE);
  3278.  
  3279.             if (!iff.raw)
  3280.             {   strcpy(tempstring1, "Page type:           ");
  3281.                 if (contents[which].DataPtr[0] == 0)
  3282.                 {   strcat(tempstring1, "None");
  3283.                 } elif (contents[which].DataPtr[0] == 1)
  3284.                 {   strcat(tempstring1, "Left");
  3285.                 } elif (contents[which].DataPtr[0] == 2)
  3286.                 {   strcat(tempstring1, "Right");
  3287.                 } elif (contents[which].DataPtr[0] == 3)
  3288.                 {   strcat(tempstring1, "Both");
  3289.                 } else strcat(tempstring1, "?");
  3290.                 addreactionnode(&List2, tempstring1);
  3291.  
  3292.                 strcpy(tempstring1, "First page?          ");
  3293.                 if (contents[which].DataPtr[1] == 0)
  3294.                 {   strcat(tempstring1, "No");
  3295.                 } else strcat(tempstring1, "Yes");
  3296.                 addreactionnode(&List2, tempstring1);
  3297.         }   }
  3298.         elif (!strcmp(contents[which].name, "PCTS"))
  3299.         {   chunkdesc("Begin picture section", TRUE);
  3300.  
  3301.             if (!iff.raw)
  3302.             {   strcpy(tempstring1, "Bitplanes:           ");
  3303.                 uvalue = contents[which].DataPtr[0]; // UBYTE
  3304.                 stcl_d(tempstring2, uvalue);
  3305.                 strcat(tempstring1, tempstring2);
  3306.                 addreactionnode(&List2, tempstring1);
  3307.         }   }
  3308.         elif (!strcmp(contents[which].name, "PARA"))
  3309.         {   chunkdesc("New paragraph format", TRUE);
  3310.  
  3311.         if (!iff.raw)
  3312.         {
  3313.             strcpy(tempstring1, "Left indent:         ");
  3314.             uvalue = getuword(contents[which].DataPtr); // UWORD
  3315.             stcl_d(tempstring2, uvalue);
  3316.             strcat(tempstring1, tempstring2);
  3317.             strcat(tempstring1, " decipoints");
  3318.             addreactionnode(&List2, tempstring1);
  3319.  
  3320.             strcpy(tempstring1, "Left margin:         ");
  3321.             uvalue = getuword(&(contents[which].DataPtr[2])); // UWORD
  3322.             stcl_d(tempstring2, uvalue);
  3323.             strcat(tempstring1, tempstring2);
  3324.             strcat(tempstring1, " decipoints");
  3325.             addreactionnode(&List2, tempstring1);
  3326.  
  3327.             strcpy(tempstring1, "Right margin:        ");
  3328.             uvalue = getuword(&(contents[which].DataPtr[4])); // UWORD
  3329.             stcl_d(tempstring2, uvalue);
  3330.             strcat(tempstring1, tempstring2);
  3331.             strcat(tempstring1, " decipoints");
  3332.             addreactionnode(&List2, tempstring1);
  3333.  
  3334.             strcpy(tempstring1, "Line spacing:        ");
  3335.             if (contents[which].DataPtr[6] == 0)
  3336.             {   strcat(tempstring1, "Single");
  3337.             } elif (contents[which].DataPtr[6] == 16)
  3338.             {   strcat(tempstring1, "Double");
  3339.             } else
  3340.             {   strcat(tempstring1, "?");
  3341.             }
  3342.             addreactionnode(&List2, tempstring1);
  3343.  
  3344.             strcpy(tempstring1, "Justification:       ");
  3345.             if (contents[which].DataPtr[7] == 0)
  3346.             {   strcat(tempstring1, "Left");
  3347.             } elif (contents[which].DataPtr[7] == 1)
  3348.             {   strcat(tempstring1, "Centre");
  3349.             } elif (contents[which].DataPtr[7] == 2)
  3350.             {   strcat(tempstring1, "Right");
  3351.             } elif (contents[which].DataPtr[7] == 3)
  3352.             {   strcat(tempstring1, "Full");
  3353.             } else
  3354.             {   strcat(tempstring1, "?");
  3355.             }
  3356.             addreactionnode(&List2, tempstring1);
  3357.  
  3358.             strcpy(tempstring1, "Font number:         ");
  3359.             uvalue = contents[which].DataPtr[8]; // UBYTE
  3360.             stcl_d(tempstring2, uvalue);
  3361.             strcat(tempstring1, tempstring2);
  3362.             addreactionnode(&List2, tempstring1);
  3363.  
  3364.             strcat(tempstring1, " Style:");
  3365.             addreactionnode(&List2, tempstring1);
  3366.  
  3367.             strcat(tempstring1, " Underlined?         ");
  3368.             if (contents[which].DataPtr[9] & 1)
  3369.             {   strcat(tempstring1, "Yes");
  3370.             } else strcat(tempstring1, "No");
  3371.             addreactionnode(&List2, tempstring1);
  3372.  
  3373.             strcat(tempstring1, " Bold?               ");
  3374.             if (contents[which].DataPtr[9] & 2)
  3375.             {   strcat(tempstring1, "Yes");
  3376.             } else strcat(tempstring1, "No");
  3377.             addreactionnode(&List2, tempstring1);
  3378.  
  3379.             strcat(tempstring1, " Italic?             ");
  3380.             if (contents[which].DataPtr[9] & 4)
  3381.             {   strcat(tempstring1, "Yes");
  3382.             } else strcat(tempstring1, "No");
  3383.             addreactionnode(&List2, tempstring1);
  3384.  
  3385.             strcat(tempstring1, " Extended?           ");
  3386.             if (contents[which].DataPtr[9] & 8)
  3387.             {   strcat(tempstring1, "Yes");
  3388.             } else strcat(tempstring1, "No");
  3389.             addreactionnode(&List2, tempstring1);
  3390.  
  3391.             strcat(tempstring1, " ColourFont?         ");
  3392.             if (contents[which].DataPtr[9] & 64)
  3393.             {   strcat(tempstring1, "Yes");
  3394.             } else strcat(tempstring1, "No");
  3395.             addreactionnode(&List2, tempstring1);
  3396.  
  3397.             strcat(tempstring1, " Tagged?             ");
  3398.             if (contents[which].DataPtr[9] & 128)
  3399.             {   strcat(tempstring1, "Yes");
  3400.             } else strcat(tempstring1, "No");
  3401.             addreactionnode(&List2, tempstring1);
  3402.  
  3403.             strcpy(tempstring1, "Miscellaneous style: ");
  3404.             if (contents[which].DataPtr[10] == 0)
  3405.             {   strcat(tempstring1, "None");
  3406.             } elif (contents[which].DataPtr[10] == 1)
  3407.             {   strcat(tempstring1, "Superscript");
  3408.             } elif (contents[which].DataPtr[10] == 2)
  3409.             {   strcat(tempstring1, "Subscript");
  3410.             } else
  3411.             {   strcat(tempstring1, "?");
  3412.             }
  3413.             addreactionnode(&List2, tempstring1);
  3414.  
  3415.             strcpy(tempstring1, "Colour:              ");
  3416.             uvalue = contents[which].DataPtr[11]; // UBYTE
  3417.             stcl_d(tempstring2, uvalue);
  3418.             strcat(tempstring1, tempstring2);
  3419.             addreactionnode(&List2, tempstring1);
  3420.         }   }
  3421.         elif (!strcmp(contents[which].name, "TABS"))
  3422.         {   chunkdesc("New tab stop types/locations", TRUE);
  3423.  
  3424.         if (!iff.raw)
  3425.         {
  3426.             strcpy(tempstring1, "Position:            ");
  3427.             uvalue = getuword(contents[which].DataPtr); // UWORD
  3428.             stcl_d(tempstring2, uvalue);
  3429.             strcat(tempstring1, tempstring2);
  3430.             strcat(tempstring1, " decipoints");
  3431.             addreactionnode(&List2, tempstring1);
  3432.  
  3433.             strcpy(tempstring1, "Type:                ");
  3434.             if (contents[which].DataPtr[2] == 0)
  3435.             {   strcat(tempstring1, "Left");
  3436.             } elif (contents[which].DataPtr[2] == 1)
  3437.             {   strcat(tempstring1, "Centre");
  3438.             } elif (contents[which].DataPtr[2] == 2)
  3439.             {   strcat(tempstring1, "Right");
  3440.             } elif (contents[which].DataPtr[2] == 3)
  3441.             {   strcat(tempstring1, "Decimal");
  3442.             } else
  3443.             {   strcat(tempstring1, "?");
  3444.             }
  3445.             addreactionnode(&List2, tempstring1);
  3446.         }   }
  3447.         elif (!strcmp(contents[which].name, "PAGE"))
  3448.         {   chunkdesc("Page break", FALSE);
  3449.         } elif (!strcmp(contents[which].name, "TEXT"))
  3450.         {   chunkdesc("Paragraph text", FALSE);
  3451.         } elif (!strcmp(contents[which].name, "PINF"))
  3452.         {   chunkdesc("Picture info", TRUE);
  3453.  
  3454.         if (!iff.raw)
  3455.         {
  3456.             strcpy(tempstring1, "Width:               ");
  3457.             uvalue = getuword(contents[which].DataPtr); // UWORD
  3458.             stcl_d(tempstring2, uvalue);
  3459.             strcat(tempstring1, tempstring2);
  3460.             addreactionnode(&List2, tempstring1);
  3461.  
  3462.             strcpy(tempstring1, "Height:              ");
  3463.             uvalue = getuword(&(contents[which].DataPtr[2])); // UWORD
  3464.             stcl_d(tempstring2, uvalue);
  3465.             strcat(tempstring1, tempstring2);
  3466.             addreactionnode(&List2, tempstring1);
  3467.  
  3468.             strcpy(tempstring1, "Page:                ");
  3469.             uvalue = getuword(&(contents[which].DataPtr[4])); // UWORD
  3470.             stcl_d(tempstring2, uvalue);
  3471.             strcat(tempstring1, tempstring2);
  3472.             addreactionnode(&List2, tempstring1);
  3473.  
  3474.             strcpy(tempstring1, "X-position:          ");
  3475.             uvalue = getuword(&(contents[which].DataPtr[6])); // UWORD
  3476.             stcl_d(tempstring2, uvalue);
  3477.             strcat(tempstring1, tempstring2);
  3478.             strcat(tempstring1, " decipoints");
  3479.             addreactionnode(&List2, tempstring1);
  3480.  
  3481.             strcpy(tempstring1, "Y-position:          ");
  3482.             uvalue = getuword(&(contents[which].DataPtr[8])); // UWORD
  3483.             stcl_d(tempstring2, uvalue);
  3484.             strcat(tempstring1, tempstring2);
  3485.             strcat(tempstring1, " decipoints");
  3486.             addreactionnode(&List2, tempstring1);
  3487.  
  3488.             strcpy(tempstring1, "Masking:            ");
  3489.             if (contents[which].DataPtr[10] == 0)
  3490.             {   strcat(tempstring1, "0 (Opaque)");
  3491.             } elif (contents[which].DataPtr[10] == 1)
  3492.             {   strcat(tempstring1, "1 (Mask plane)");
  3493.             } elif (contents[which].DataPtr[10] == 2)
  3494.             {   strcat(tempstring1, "2 (Transparent colour)");
  3495.             } elif (contents[which].DataPtr[10] == 3)
  3496.             {   strcat(tempstring1, "3 (Lasso)");
  3497.             } else strcat(tempstring1, "?");
  3498.             addreactionnode(&List2, tempstring1);
  3499.  
  3500.             strcpy(tempstring1, "Compression:        ");
  3501.             if (contents[which].DataPtr[11] == 0)
  3502.             {   strcat(tempstring1, "None");
  3503.             } elif (contents[which].DataPtr[11] == 1)
  3504.             {   strcat(tempstring1, "Byte run encoding");
  3505.             } else strcat(tempstring1, "?");
  3506.             addreactionnode(&List2, tempstring1);
  3507.  
  3508.             strcpy(tempstring1, "Transparent colour: ");
  3509.             if (contents[which].DataPtr[12] != 2
  3510.              && contents[which].DataPtr[12] != 3)
  3511.             {   strcat(tempstring1, "n/a");
  3512.             } else
  3513.             {   stcl_d(tempstring2, (256 * contents[which].DataPtr[12])
  3514.                                   +        contents[which].DataPtr[13]);
  3515.                 strcat(tempstring1, tempstring2);
  3516.             }
  3517.             addreactionnode(&List2, tempstring1);
  3518.     }   }   }
  3519.     elif (!strcmp(queryform, "AIFF"))
  3520.     {   if (!strcmp(contents[which].name, "MIDI"))
  3521.         {   chunkdesc("Stores MIDI data", FALSE);
  3522.         } elif (!strcmp(contents[which].name, "MARK"))
  3523.         {   chunkdesc("Points to positions in the sound data", TRUE);
  3524.  
  3525.         if (!iff.raw)
  3526.         {
  3527.             strcpy(tempstring1, "Markers:             ");
  3528.             svalue = getsword(contents[which].DataPtr);
  3529.             stcl_d(tempstring2, svalue);
  3530.             strcat(tempstring1, tempstring2);
  3531.             if (svalue < 0)
  3532.             {   strcat(tempstring1, "!");
  3533.             }
  3534.             addreactionnode(&List2, tempstring1);
  3535.             markers = svalue;
  3536.             if (markers > 0)
  3537.             {   currentpos = 2;
  3538.                 for (i = 1; i <= markers; i++)
  3539.                 {   strcpy(tempstring1, "Marker ");
  3540.                     stcl_d(tempstring2, i);
  3541.                     strcat(tempstring1, tempstring2);
  3542.                     strcat(tempstring1, ":");
  3543.                     addreactionnode(&List2, tempstring1);
  3544.  
  3545.                     strcpy(tempstring1, " ID:                 ");
  3546.                     svalue = getsword(&(contents[which].name[currentpos]));
  3547.                     stcl_d(tempstring2, svalue);
  3548.                     strcat(tempstring1, tempstring2);
  3549.                     if (svalue < 1)
  3550.                     {   strcat(tempstring1, "!");
  3551.                     }
  3552.                     addreactionnode(&List2, tempstring1);
  3553.                     currentpos += 2;
  3554.  
  3555.                     strcpy(tempstring1, " Position:           ");
  3556.                     uvalue = getulong(&(contents[which].name[currentpos]));
  3557.                     stcl_d(tempstring2, uvalue);
  3558.                     strcat(tempstring1, tempstring2);
  3559.                     addreactionnode(&List2, tempstring1);
  3560.                     currentpos += 4;
  3561.  
  3562.                     strcpy(tempstring1, " Name:               ");
  3563.                     uvalue = contents[which].name[currentpos++];
  3564.                     // the number of characters in the string
  3565.                     if (uvalue < MEDFIELD)
  3566.                     {   strncat(tempstring1, &(contents[which].name[currentpos]), uvalue);
  3567.                     } else
  3568.                     {   strncat(tempstring1, &(contents[which].name[currentpos]), MEDFIELD);
  3569.                     }
  3570.                     addreactionnode(&List2, tempstring1);
  3571.                     currentpos += uvalue;
  3572.                     if (uvalue % 2)
  3573.                     {   currentpos++; // skip pad byte, if appropriate
  3574.         }   }   }   }   }
  3575.         elif (!strcmp(contents[which].name, "AESD"))
  3576.         {   chunkdesc("Pertinent to autio recording devices", FALSE);
  3577.         } elif (!strcmp(contents[which].name, "COMT"))
  3578.         {   chunkdesc("Stores comments", TRUE);
  3579.  
  3580.         if (!iff.raw)
  3581.         {
  3582.             strcpy(tempstring1, "Comments:            ");
  3583.             svalue = getsword(contents[which].DataPtr);
  3584.             stcl_d(tempstring2, svalue);
  3585.             strcat(tempstring1, tempstring2);
  3586.             if (svalue < 0)
  3587.             {   strcat(tempstring1, "!");
  3588.             }
  3589.             addreactionnode(&List2, tempstring1);
  3590.  
  3591.             // we could have a 'comments' variable, but we just reuse
  3592.             // the 'markers' variable.
  3593.             markers = svalue;
  3594.             if (markers > 0)
  3595.             {   currentpos = 2;
  3596.                 for (i = 1; i <= markers; i++)
  3597.                 {   strcpy(tempstring1, "Comment ");
  3598.                     stcl_d(tempstring2, i);
  3599.                     strcat(tempstring1, tempstring2);
  3600.                     strcat(tempstring1, ":");
  3601.                     addreactionnode(&List2, tempstring1);
  3602.  
  3603.                     strcpy(tempstring1, " Created on:         ");
  3604.                     uvalue = getulong(&(contents[which].DataPtr[currentpos]));
  3605.                     DateTime.dat_Stamp.ds_Days   =   uvalue / 86400;             // days since 1/1/78
  3606.                     DateTime.dat_Stamp.ds_Minute =  (uvalue % 86400) / 60;       // minutes in day
  3607.                     DateTime.dat_Stamp.ds_Tick   = ((uvalue % 86400) % 60) * 50; // ticks in minute
  3608.                     DateTime.dat_Format          = FORMAT_DOS;
  3609.                     DateTime.dat_Flags           = DTF_SUBST;
  3610.                     DateTime.dat_StrDay          = weekdaystring;
  3611.                     DateTime.dat_StrDate         = datestring;
  3612.                     DateTime.dat_StrTime         = timestring;
  3613.                     if (!DateToStr(&DateTime))
  3614.                     {   rq("DateToStr() failed!");
  3615.                     }
  3616.                     strcat(tempstring1, timestring);
  3617.                     strcat(tempstring1, " ");
  3618.                     strcat(tempstring1, weekdaystring);
  3619.                     strcat(tempstring1, " ");
  3620.                     strcat(tempstring1, datestring);
  3621.                     addreactionnode(&List2, tempstring1);
  3622.                     currentpos += 4;
  3623.  
  3624.                     strcpy(tempstring1, " Marker ID:          ");
  3625.                     svalue = getsword(&(contents[which].DataPtr[currentpos]));
  3626.                     stcl_d(tempstring2, svalue);
  3627.                     strcat(tempstring1, tempstring2);
  3628.                     if (svalue < 1)
  3629.                     {    strcat(tempstring1, "!");
  3630.                     }
  3631.                     addreactionnode(&List2, tempstring1);
  3632.                     currentpos += 2;
  3633.  
  3634.                     strcpy(tempstring1, " Comment:            ");
  3635.                     uvalue = getuword(&(contents[which].DataPtr[currentpos]));
  3636.                     // the number of characters in the string
  3637.                     currentpos += 2;
  3638.                     if (uvalue < MEDFIELD)
  3639.                     {   strncat(tempstring1, &(contents[which].name[currentpos]), uvalue);
  3640.                     } else
  3641.                     {   strncat(tempstring1, &(contents[which].name[currentpos]), MEDFIELD);
  3642.                     }
  3643.                     addreactionnode(&List2, tempstring1);
  3644.                     currentpos += uvalue;
  3645.                     if (uvalue % 2)
  3646.                     {   currentpos++; // skip pad byte, if appropriate
  3647.         }   }   }   }   }
  3648.         elif (!strcmp(contents[which].name, "COMM"))
  3649.         {   chunkdesc("Fundamental parameters for the sampled sound", TRUE);
  3650.  
  3651.         if (!iff.raw)
  3652.         {
  3653.             strcpy(tempstring1, "Channels:            ");
  3654.             svalue = getsword(contents[which].DataPtr);
  3655.             stcl_d(tempstring2, svalue);
  3656.             strcat(tempstring1, tempstring2);
  3657.             if (svalue == 1)
  3658.             {   strcat(tempstring1, " (mono)");
  3659.             } elif (svalue == 2)
  3660.             {   strcat(tempstring1, " (stereo)");
  3661.             } elif (svalue > 2)
  3662.             {   strcat(tempstring1, " (surround)");
  3663.             }
  3664.             addreactionnode(&List2, tempstring1);
  3665.  
  3666.             strcpy(tempstring1, "Sample frames:       ");
  3667.             uvalue = getulong(&(contents[which].DataPtr[2]));
  3668.             stcl_d(tempstring2, uvalue);
  3669.             strcat(tempstring1, tempstring2);
  3670.             addreactionnode(&List2, tempstring1);
  3671.  
  3672.             strcpy(tempstring1, "Sample quality:      ");
  3673.             svalue = getsword(&(contents[which].DataPtr[6]));
  3674.             stcl_d(tempstring2, svalue);
  3675.             strcat(tempstring1, tempstring2);
  3676.             strcat(tempstring1, "-bit");
  3677.             addreactionnode(&List2, tempstring1);
  3678.  
  3679.             /* This is an 80-bit IEEE 754 Apple-style (SANE) floating
  3680.             point number (not yet implemented):
  3681.                  79 Sign
  3682.               64:78 Exponent
  3683.                0:63 Mantissa */
  3684.             strcpy(tempstring1, "Playback rate:       -");
  3685.             addreactionnode(&List2, tempstring1);
  3686.         }   }
  3687.         elif (!strcmp(contents[which].name, "APPL"))
  3688.         {   chunkdesc("Application-specific data", TRUE);
  3689.  
  3690.             if (!iff.raw)
  3691.             {   strcpy(tempstring1, "Application:         ");
  3692.                 strcat(tempstring1, contents[which].DataPtr);
  3693.                 if (!strcmp(tempstring1, "pdos"))
  3694.                 {   strcat(tempstring1, " (Apple II)");
  3695.                 }
  3696.                 addreactionnode(&List2, tempstring1);
  3697.         }   }
  3698.         elif (!strcmp(contents[which].name, "SSND"))
  3699.         {   chunkdesc("The actual sample frames", TRUE);
  3700.  
  3701.             if (!iff.raw)
  3702.             {   strcpy(tempstring1, "Offset:              ");
  3703.                 uvalue = getulong(contents[which].DataPtr);
  3704.                 stcl_d(tempstring2, uvalue);
  3705.                 strcat(tempstring1, tempstring2);
  3706.                 addreactionnode(&List2, tempstring1);
  3707.  
  3708.                 strcpy(tempstring1, "Block size:          ");
  3709.                 uvalue = getulong(&(contents[which].DataPtr[4]));
  3710.                 stcl_d(tempstring2, uvalue);
  3711.                 strcat(tempstring1, tempstring2);
  3712.                 addreactionnode(&List2, tempstring1);
  3713.         }   }
  3714.         elif (!strcmp(contents[which].name, "INST"))
  3715.         {   chunkdesc("Instrument chunk", TRUE);
  3716.  
  3717.         if (!iff.raw)
  3718.         {
  3719.             strcpy(tempstring1, "Base note:           ");
  3720.             svalue = getsbyte(&(contents[which].DataPtr[0]));
  3721.             stcl_d(tempstring2, svalue);
  3722.             strcat(tempstring1, tempstring2);
  3723.             if (svalue < 0 || svalue > 127)
  3724.                 strcat(tempstring1, "!");
  3725.             addreactionnode(&List2, tempstring1);
  3726.  
  3727.             strcpy(tempstring1, "Detune:              ");
  3728.             svalue = getsbyte(&(contents[which].DataPtr[1]));
  3729.             stcl_d(tempstring2, svalue);
  3730.             strcat(tempstring1, tempstring2);
  3731.             if (svalue < -50 || svalue > 50)
  3732.                 strcat(tempstring1, "!");
  3733.             addreactionnode(&List2, tempstring1);
  3734.  
  3735.             strcpy(tempstring1, "Low note:            ");
  3736.             svalue = getsbyte(&(contents[which].DataPtr[2]));
  3737.             stcl_d(tempstring2, svalue);
  3738.             strcat(tempstring1, tempstring2);
  3739.             if (svalue < 0 || svalue > 127)
  3740.                 strcat(tempstring1, "!");
  3741.             addreactionnode(&List2, tempstring1);
  3742.  
  3743.             strcpy(tempstring1, "High note:           ");
  3744.             svalue = getsbyte(&(contents[which].DataPtr[3]));
  3745.             stcl_d(tempstring2, svalue);
  3746.             strcat(tempstring1, tempstring2);
  3747.             if (svalue < 0 || svalue > 127)
  3748.                 strcat(tempstring1, "!");
  3749.             addreactionnode(&List2, tempstring1);
  3750.  
  3751.             strcpy(tempstring1, "Low velocity:        ");
  3752.             svalue = getsbyte(&(contents[which].DataPtr[4]));
  3753.             stcl_d(tempstring2, svalue);
  3754.             strcat(tempstring1, tempstring2);
  3755.             if (svalue < 1 || svalue > 127)
  3756.                 strcat(tempstring1, "!");
  3757.             addreactionnode(&List2, tempstring1);
  3758.  
  3759.             strcpy(tempstring1, "High velocity:       ");
  3760.             svalue = getsbyte(&(contents[which].DataPtr[5]));
  3761.             stcl_d(tempstring2, svalue);
  3762.             strcat(tempstring1, tempstring2);
  3763.             if (svalue < 1 || svalue > 127)
  3764.                 strcat(tempstring1, "!");
  3765.             addreactionnode(&List2, tempstring1);
  3766.  
  3767.             strcpy(tempstring1, "Gain:                ");
  3768.             svalue = getsword(&(contents[which].DataPtr[6]));
  3769.             stcl_d(tempstring2, svalue);
  3770.             strcat(tempstring1, tempstring2);
  3771.             addreactionnode(&List2, tempstring1);
  3772.  
  3773.             strcpy(tempstring1, "Sustain loop:");
  3774.             svalue = getsword(&(contents[which].DataPtr[8]));
  3775.             if (svalue == 0)
  3776.             {   strcpy(tempstring1, " No looping");
  3777.             } elif (svalue == 1)
  3778.             {   strcpy(tempstring1, " Forwards looping");
  3779.             } elif (svalue == 2)
  3780.             {   strcpy(tempstring1, " Forwards/backwards looping");
  3781.             } else
  3782.             {   strcpy(tempstring1, " ?");
  3783.             }
  3784.             addreactionnode(&List2, tempstring1);
  3785.             strcpy(tempstring1, " Begin loop:         ");
  3786.             svalue = getsword(&(contents[which].DataPtr[10]));
  3787.             stcl_d(tempstring1, svalue);
  3788.             addreactionnode(&List2, tempstring1);
  3789.             strcpy(tempstring1, " End loop:           ");
  3790.             svalue = getsword(&(contents[which].DataPtr[12]));
  3791.             stcl_d(tempstring1, svalue);
  3792.             addreactionnode(&List2, tempstring1);
  3793.  
  3794.             strcpy(tempstring1, "Release loop:        ");
  3795.  
  3796.             svalue = getsword(&(contents[which].DataPtr[14]));
  3797.             if (svalue == 0)
  3798.             {   strcpy(tempstring1, " No looping");
  3799.             } elif (svalue == 1)
  3800.             {   strcpy(tempstring1, " Forwards looping");
  3801.             } elif (svalue == 2)
  3802.             {   strcpy(tempstring1, " Forwards/backwards looping");
  3803.             } else
  3804.             {   strcpy(tempstring1, " ?");
  3805.             }
  3806.             addreactionnode(&List2, tempstring1);
  3807.             strcpy(tempstring1, " Begin loop:         ");
  3808.             svalue = getsword(&(contents[which].DataPtr[16]));
  3809.             stcl_d(tempstring1, svalue);
  3810.             addreactionnode(&List2, tempstring1);
  3811.             strcpy(tempstring1, " End loop:           ");
  3812.             svalue = getsword(&(contents[which].DataPtr[18]));
  3813.             stcl_d(tempstring1, svalue);
  3814.             addreactionnode(&List2, tempstring1);
  3815.     }   }   }
  3816.     elif (!strcmp(queryform, "8SVX"))
  3817.     {   if (!strcmp(contents[which].name, "ATAK"))
  3818.         {   chunkdesc("Gives attack amplitude contour (envelope)", FALSE);
  3819.         } elif (!strcmp(contents[which].name, "RLSE"))
  3820.         {   chunkdesc("Gives release amplitude contour (envelope)", FALSE);
  3821.         } elif (!strcmp(contents[which].name, "BODY"))
  3822.         {   chunkdesc("Sound data chunk", FALSE);
  3823.         } elif (!strcmp(contents[which].name, "FADE"))
  3824.         {   chunkdesc("Fade away to silence", TRUE);
  3825.  
  3826.             if (!iff.raw)
  3827.             {   strcpy(tempstring1, "Fade start:          ");
  3828.                 uvalue = getulong(contents[which].DataPtr);
  3829.                 stcl_d(tempstring2, uvalue);
  3830.                 strcat(tempstring1, tempstring2);
  3831.                 addreactionnode(&List2, tempstring1);
  3832.         }   }
  3833.         elif (!strcmp(contents[which].name, "SEQN"))
  3834.         {   chunkdesc("Multiple loop sequencing", TRUE);
  3835.  
  3836.         if (!iff.raw)
  3837.         {
  3838.             currentpos = 0;
  3839.             while (currentpos < contents[which].bytes)
  3840.             {   strcpy(tempstring1, "Loop start:          ");
  3841.                 uvalue = getulong(&(contents[which].DataPtr[currentpos]));
  3842.                 stcl_d(tempstring2, uvalue);
  3843.                 strcat(tempstring1, tempstring2);
  3844.                 if (uvalue % 4)
  3845.                 {   strcat(tempstring1, "!");
  3846.                 }
  3847.                 addreactionnode(&List2, tempstring1);
  3848.                 currentpos += 4;
  3849.  
  3850.                 strcpy(tempstring1, "Loop end:            ");
  3851.                 uvalue = getulong(&(contents[which].DataPtr[currentpos]));
  3852.                 stcl_d(tempstring2, uvalue);
  3853.                 strcat(tempstring1, tempstring2);
  3854.                 if (uvalue % 4)
  3855.                 {   strcat(tempstring1, "!");
  3856.                 }
  3857.                 addreactionnode(&List2, tempstring1);
  3858.                 currentpos += 4;
  3859.         }   }   }
  3860.         elif (!strcmp(contents[which].name, "CHAN"))
  3861.         {   chunkdesc("Specified channel, or combination of channels", TRUE);
  3862.  
  3863.             if (!iff.raw)
  3864.             {   strcpy(tempstring1, "Channel:             ");
  3865.                 svalue = getslong(contents[which].DataPtr);
  3866.                 if (svalue == 2)
  3867.                 {   strcat(tempstring1, "Left");
  3868.                 } elif (svalue == 4)
  3869.                 {   strcat(tempstring1, "Right");
  3870.                 } elif (svalue == 6)
  3871.                 {   strcat(tempstring1, "Stereo (both)");
  3872.                 } else strcat(tempstring1, "?");
  3873.                 addreactionnode(&List2, tempstring1);
  3874.         }   }
  3875.         elif (!strcmp(contents[which].name, "PAN "))
  3876.         {   chunkdesc("Stereo sound using a single array of data", TRUE);
  3877.  
  3878.             if (!iff.raw)
  3879.             {   strcpy(tempstring1, "Sound position:      ");
  3880.                 svalue = getslong(contents[which].DataPtr);
  3881.                 stcl_d(tempstring2, svalue);
  3882.                 strcat(tempstring1, tempstring2);
  3883.                 strcat(tempstring1, "/65536 ");
  3884.                 if (svalue < 32768)
  3885.                 {    strcat(tempstring1, "(left)");
  3886.                 } elif (svalue > 32678)
  3887.                 {    strcat(tempstring1, "(right)");
  3888.                 } else
  3889.                 {    // assert(svalue == 32678);
  3890.                      strcat(tempstring1, "(centre)");
  3891.                 }
  3892.                 addreactionnode(&List2, tempstring1);
  3893.         }   }
  3894.         elif (!strcmp(contents[which].name, "VHDR"))
  3895.         {   chunkdesc("Playback parameters for the sampled waveforms", TRUE);
  3896.  
  3897.             if (!iff.raw)
  3898.             {   strcpy(tempstring1, "1-shot samples:      ");
  3899.                 uvalue = getulong(contents[which].DataPtr);
  3900.                 stcl_d(tempstring2, uvalue);
  3901.                 strcat(tempstring1, tempstring2);
  3902.                 addreactionnode(&List2, tempstring1);
  3903.  
  3904.                 strcpy(tempstring1, "Repeat samples:      ");
  3905.                 uvalue = getulong(&(contents[which].DataPtr[4]));
  3906.                 stcl_d(tempstring2, uvalue);
  3907.                 strcat(tempstring1, tempstring2);
  3908.                 addreactionnode(&List2, tempstring1);
  3909.  
  3910.                 strcpy(tempstring1, "Samples per cycle:   ");
  3911.                 uvalue = getulong(&(contents[which].DataPtr[8]));
  3912.                 stcl_d(tempstring2, uvalue);
  3913.                 strcat(tempstring1, tempstring2);
  3914.                 addreactionnode(&List2, tempstring1);
  3915.  
  3916.                 strcpy(tempstring1, "Sampling rate:       ");
  3917.                 uvalue = getuword(&(contents[which].DataPtr[12]));
  3918.                 stcl_d(tempstring2, uvalue);
  3919.                 strcat(tempstring1, tempstring2);
  3920.                 addreactionnode(&List2, tempstring1);
  3921.  
  3922.                 strcpy(tempstring1, "Octaves:             ");
  3923.                 uvalue = contents[which].DataPtr[14]; // UBYTE
  3924.                 stcl_d(tempstring2, uvalue);
  3925.                 strcat(tempstring1, tempstring2);
  3926.                 addreactionnode(&List2, tempstring1);
  3927.  
  3928.                 strcpy(tempstring1, "Compression:         "); // UBYTE
  3929.                 if (contents[which].DataPtr[15] == 0)
  3930.                 {   strcat(tempstring1, "None");
  3931.                 } elif (contents[which].DataPtr[15] == 1)
  3932.                 {   strcat(tempstring1, "Fibonacci-delta encoding");
  3933.                 } else strcat(tempstring1, "?");
  3934.                 addreactionnode(&List2, tempstring1);
  3935.  
  3936.                 strcpy(tempstring1, "Volume:              ");
  3937.                 svalue = getslong(&(contents[which].DataPtr[16]));
  3938.                 svalue /= 1024; // LONG (Fixed)
  3939.                 stcl_d(tempstring2, svalue);
  3940.                 strcat(tempstring1, tempstring2);
  3941.                 strcat(tempstring1, "/64");
  3942.                 addreactionnode(&List2, tempstring1);
  3943.     }   }   }
  3944.     elif (!strcmp(queryform, "ILBM") || !strcmp(queryform, "ABCM") || !strcmp(queryform, "ANIM"))
  3945.     {   if (!strcmp(contents[which].name, "CAMG"))
  3946.         {   chunkdesc("Amiga display mode of a picture", TRUE);
  3947.  
  3948.             if (!iff.raw)
  3949.             {   strcpy(tempstring1, "ModeID:             $");
  3950.                 hexalize(contents[which].DataPtr[0]);
  3951.                 hexalize(contents[which].DataPtr[1]);
  3952.                 hexalize(contents[which].DataPtr[2]);
  3953.                 hexalize(contents[which].DataPtr[3]);
  3954.                 addreactionnode(&List2, tempstring1);
  3955.         }   }
  3956.         elif (!strcmp(queryform, "ANIM") && !strcmp(contents[which].name, "ANHD"))
  3957.         {   chunkdesc("Animation header", TRUE);
  3958.  
  3959.         if (!iff.raw)
  3960.         {
  3961.             strcpy(tempstring1, "Compression method:     ");
  3962.             if (contents[which].DataPtr[0] == 0)
  3963.             {   strcat(tempstring1, "0 (set directly)");
  3964.             } elif (contents[which].DataPtr[0] == 1)
  3965.             {   strcat(tempstring1, "1 (XOR ILBM)");
  3966.             } elif (contents[which].DataPtr[0] == 2)
  3967.             {   strcat(tempstring1, "2 (long delta)");
  3968.             } elif (contents[which].DataPtr[0] == 3)
  3969.             {   strcat(tempstring1, "3 (short delta)");
  3970.             } elif (contents[which].DataPtr[0] == 4)
  3971.             {   strcat(tempstring1, "4 (short/long delta)");
  3972.             } elif (contents[which].DataPtr[0] == 5)
  3973.             {   strcat(tempstring1, "5 (byte vertical delta)");
  3974.             } elif (contents[which].DataPtr[0] == 6)
  3975.             {   strcat(tempstring1, "6 (stereo op 5)");
  3976.             } elif (contents[which].DataPtr[0] == 74) // not a typo
  3977.             {   strcat(tempstring1, "7 (Eric Graham)");
  3978.             } else
  3979.             {   strcat(tempstring1, "?");
  3980.             }
  3981.             addreactionnode(&List2, tempstring1);
  3982.  
  3983.             strcpy(tempstring1, "Mask:                   %");
  3984.             binarize(contents[which].DataPtr[1]);
  3985.             addreactionnode(&List2, tempstring1);
  3986.  
  3987.             strcpy(tempstring1, "Entire width:           ");
  3988.             uvalue = getuword(&contents[which].DataPtr[2]); // UWORD
  3989.             stcl_d(tempstring2, uvalue);
  3990.             strcat(tempstring1, tempstring2);
  3991.             strcat(tempstring1, " pixels");
  3992.             addreactionnode(&List2, tempstring1);
  3993.  
  3994.             strcpy(tempstring1, "Entire height:          ");
  3995.             uvalue = getuword(&contents[which].DataPtr[4]); // UWORD
  3996.             stcl_d(tempstring2, uvalue);
  3997.             strcat(tempstring1, tempstring2);
  3998.             strcat(tempstring1, " pixels");
  3999.             addreactionnode(&List2, tempstring1);
  4000.  
  4001.             strcpy(tempstring1, "Width:                  ");
  4002.             svalue = getsword(&contents[which].DataPtr[6]); // WORD
  4003.             stcl_d(tempstring2, svalue);
  4004.             strcat(tempstring1, tempstring2);
  4005.             strcat(tempstring1, " pixels");
  4006.             addreactionnode(&List2, tempstring1);
  4007.  
  4008.             strcpy(tempstring1, "Height:                 ");
  4009.             svalue = getsword(&contents[which].DataPtr[8]); // WORD
  4010.             stcl_d(tempstring2, svalue);
  4011.             strcat(tempstring1, tempstring2);
  4012.             strcat(tempstring1, " pixels");
  4013.             addreactionnode(&List2, tempstring1);
  4014.  
  4015.             strcpy(tempstring1, "Absolute time:          ");
  4016.             uvalue = getulong(&contents[which].DataPtr[10]); // ULONG
  4017.             stcl_d(tempstring2, uvalue);
  4018.             strcat(tempstring1, tempstring2);
  4019.             strcat(tempstring1, "/60 of a second");
  4020.             addreactionnode(&List2, tempstring1);
  4021.  
  4022.             strcpy(tempstring1, "Relative time:          ");
  4023.             uvalue = getulong(&contents[which].DataPtr[14]); // ULONG
  4024.             stcl_d(tempstring2, uvalue);
  4025.             strcat(tempstring1, tempstring2);
  4026.             strcat(tempstring1, "/60 of a second");
  4027.             addreactionnode(&List2, tempstring1);
  4028.  
  4029.             strcpy(tempstring1, "Interleave:             ");
  4030.             if (contents[which].DataPtr[18] == 0)
  4031.             {   strcat(tempstring1, "0 (2 frames back)");
  4032.             } else
  4033.             {   stcl_d(tempstring2, contents[which].DataPtr[18]);
  4034.                 strcat(tempstring1, tempstring2);
  4035.                 strcat(tempstring1, " frames back");
  4036.             }
  4037.             addreactionnode(&List2, tempstring1);
  4038.  
  4039.             // now a pad byte (19)
  4040.  
  4041.             strcpy(tempstring1, "Flags:");
  4042.             uvalue = getulong(&contents[which].DataPtr[20]); // ULONG
  4043.  
  4044.             strcpy(tempstring1, " Data length:           ");
  4045.             if (uvalue & 1)
  4046.             {   strcat(tempstring1, "Long");
  4047.             } else
  4048.             {   strcat(tempstring1, "Short");
  4049.             }
  4050.             addreactionnode(&List2, tempstring1);
  4051.  
  4052.             strcpy(tempstring1, " Set/XOR:               ");
  4053.             if (uvalue & 2)
  4054.             {   strcat(tempstring1, "Set");
  4055.             } else
  4056.             {   strcat(tempstring1, "XOR");
  4057.             }
  4058.             addreactionnode(&List2, tempstring1);
  4059.  
  4060.             strcpy(tempstring1, " Info:                  ");
  4061.             if (uvalue & 4)
  4062.             {   strcat(tempstring1, "One info list for all planes");
  4063.             } else
  4064.             {   strcat(tempstring1, "Separate info for each plane");
  4065.             }
  4066.             addreactionnode(&List2, tempstring1);
  4067.  
  4068.             strcpy(tempstring1, " Run length encoded?    ");
  4069.             if (uvalue & 8)
  4070.             {   strcat(tempstring1, "Yes");
  4071.             } else
  4072.             {   strcat(tempstring1, "No");
  4073.             }
  4074.             addreactionnode(&List2, tempstring1);
  4075.  
  4076.             strcpy(tempstring1, " Encoding:              ");
  4077.             if (uvalue & 16)
  4078.             {   strcat(tempstring1, "Vertical");
  4079.             } else
  4080.             {   strcat(tempstring1, "Horizontal");
  4081.             }
  4082.             addreactionnode(&List2, tempstring1);
  4083.  
  4084.             strcpy(tempstring1, " Info offsets:          ");
  4085.             if (uvalue & 32)
  4086.             {   strcat(tempstring1, "Short");
  4087.             } else
  4088.             {   strcat(tempstring1, "Long");
  4089.             }
  4090.             addreactionnode(&List2, tempstring1);
  4091.  
  4092.             // now 16 reserved bytes
  4093.         }   }
  4094.         elif (!strcmp(queryform, "ANIM") && !strcmp(contents[which].name, "DLTA"))
  4095.         {   chunkdesc("Delta compression data", FALSE);
  4096.         } elif (!strcmp(contents[which].name, "DPI "))
  4097.         {   chunkdesc("Dots per inch", TRUE);
  4098.  
  4099.             if (!iff.raw)
  4100.             {   strcpy(tempstring1, "Dots per inch:      ");
  4101.                 // There are 20 characters in the first column.
  4102.                 uvalue = getuword(contents[which].DataPtr);
  4103.                 stcl_d(tempstring2, uvalue);
  4104.                 strcat(tempstring1, tempstring2);
  4105.                 strcat(tempstring1, "x");
  4106.                 uvalue = getuword(&(contents[which].DataPtr[2]));
  4107.                 stcl_d(tempstring2, uvalue);
  4108.                 strcat(tempstring1, tempstring2);
  4109.                 addreactionnode(&List2, tempstring1);
  4110.         }   }
  4111.         elif (!strcmp(contents[which].name, "CMAP"))
  4112.         {   chunkdesc("Colour map data", FALSE);
  4113.         } elif (!strcmp(contents[which].name, "BODY"))
  4114.         {   chunkdesc("Image data chunk", FALSE);
  4115.         } elif (!strcmp(contents[which].name, "EPSF"))
  4116.         {   chunkdesc("Encapsulated PostScript representation of image", TRUE);
  4117.  
  4118.         if (!iff.raw)
  4119.         {
  4120.             strcpy(tempstring1, "Left X:             ");
  4121.             svalue = getsword(contents[which].DataPtr);
  4122.             stcl_d(tempstring2, svalue);
  4123.             strcat(tempstring1, tempstring2);
  4124.             addreactionnode(&List2, tempstring1);
  4125.  
  4126.             strcpy(tempstring1, "Top Y:              ");
  4127.             svalue = getsword(&(contents[which].DataPtr[2]));
  4128.             stcl_d(tempstring2, svalue);
  4129.             strcat(tempstring1, tempstring2);
  4130.             addreactionnode(&List2, tempstring1);
  4131.  
  4132.             strcpy(tempstring1, "Right X:            ");
  4133.             svalue = getsword(&(contents[which].DataPtr[4]));
  4134.             stcl_d(tempstring2, svalue);
  4135.             strcat(tempstring1, tempstring2);
  4136.             addreactionnode(&List2, tempstring1);
  4137.  
  4138.             strcpy(tempstring1, "Bottom Y:           ");
  4139.             svalue = getsword(&(contents[which].DataPtr[6]));
  4140.             stcl_d(tempstring2, svalue);
  4141.             strcat(tempstring1, tempstring2);
  4142.             addreactionnode(&List2, tempstring1);
  4143.         }   }
  4144.         elif (!strcmp(contents[which].name, "DEST"))
  4145.         {   chunkdesc("Scatter bitplanes into a deeper destination image", TRUE);
  4146.  
  4147.         if (!iff.raw)
  4148.         {
  4149.             strcpy(tempstring1, "Source bitplanes:   ");
  4150.             stcl_d(tempstring2, contents[which].DataPtr[0]);
  4151.             strcat(tempstring1, tempstring2);
  4152.             addreactionnode(&List2, tempstring1);
  4153.  
  4154.             // next (1) is a pad byte.
  4155.  
  4156.             strcpy(tempstring1, "PlanePick:          %"); // UWORD
  4157.             binarize(contents[which].DataPtr[2]);
  4158.             binarize(contents[which].DataPtr[3]);
  4159.             addreactionnode(&List2, tempstring1);
  4160.  
  4161.             strcpy(tempstring1, "PlaneOnOff:         %"); // UWORD
  4162.             binarize(contents[which].DataPtr[4]);
  4163.             binarize(contents[which].DataPtr[5]);
  4164.             addreactionnode(&List2, tempstring1);
  4165.  
  4166.             strcpy(tempstring1, "PlaneMask:          %"); // UWORD
  4167.             binarize(contents[which].DataPtr[6]);
  4168.             binarize(contents[which].DataPtr[7]);
  4169.             addreactionnode(&List2, tempstring1);
  4170.         }   }
  4171.         elif (!strcmp(contents[which].name, "GRAB"))
  4172.         {   chunkdesc("Locates a hotspot, when used as a pointer or brush", TRUE);
  4173.  
  4174.             if (!iff.raw)
  4175.             {   strcpy(tempstring1, "Hotspot:            ");
  4176.                 svalue = getsword(contents[which].DataPtr);
  4177.                 stcl_d(tempstring2, svalue);
  4178.                 strcat(tempstring1, tempstring2);
  4179.                 strcat(tempstring1, ",");
  4180.                 svalue = getsword(&(contents[which].DataPtr[2]));
  4181.                 stcl_d(tempstring2, svalue);
  4182.                 strcat(tempstring1, tempstring2);
  4183.                 addreactionnode(&List2, tempstring1);
  4184.         }   }
  4185.         elif (!strcmp(contents[which].name, "SPRT"))
  4186.         {   chunkdesc("This image is intended as a sprite", TRUE);
  4187.  
  4188.             if (!iff.raw)
  4189.             {   strcpy(tempstring1, "Precedence:         ");
  4190.                 uvalue = getuword(contents[which].DataPtr);
  4191.  
  4192.                 stcl_d(tempstring2, uvalue);
  4193.                 strcat(tempstring1, tempstring2);
  4194.                 addreactionnode(&List2, tempstring1);
  4195.         }   }
  4196.         elif (!strcmp(contents[which].name, "BMHD"))
  4197.         {   /* UWORD w, h;               0-1, 2-3
  4198.             WORD  x, y;                  4-5, 6-7
  4199.             UBYTE nPlanes;               8
  4200.             UBYTE Masking;               9
  4201.             UBYTE Compression;           10
  4202.             UBYTE pad;                   11
  4203.             UWORD transparentColour;     12-13
  4204.             UBYTE xAspect, yAspect;      14, 15
  4205.             WORD  pageWidth, pageHeight; 16-17, 18-19 */
  4206.  
  4207.             chunkdesc("Data necessary to understand the BODY chunk", TRUE);
  4208.  
  4209.             if (!iff.raw)
  4210.             {
  4211.             strcpy(tempstring1, "Image size:         ");
  4212.             stcl_d(tempstring2, (256 * contents[which].DataPtr[0])
  4213.                               +        contents[which].DataPtr[1]); // UWORD
  4214.             strcat(tempstring1, tempstring2);
  4215.             strcat(tempstring1, "x");
  4216.             stcl_d(tempstring2, (256 * contents[which].DataPtr[2])
  4217.                               +        contents[which].DataPtr[3]); // UWORD
  4218.             strcat(tempstring1, tempstring2);
  4219.             addreactionnode(&List2, tempstring1);
  4220.  
  4221.             strcpy(tempstring1, "Position:           ");
  4222.             stcl_d(tempstring2, (256 * contents[which].DataPtr[4])
  4223.                               +        contents[which].DataPtr[5]); // WORD
  4224.             strcat(tempstring1, tempstring2);
  4225.             strcat(tempstring1, ",");
  4226.             stcl_d(tempstring2, (256 * contents[which].DataPtr[6])
  4227.                               +        contents[which].DataPtr[7]); // WORD
  4228.             strcat(tempstring1, tempstring2);
  4229.             addreactionnode(&List2, tempstring1);
  4230.  
  4231.             strcpy(tempstring1, "Bitplanes:          ");
  4232.             stcl_d(tempstring2, (LONG) contents[which].DataPtr[8]);
  4233.             strcat(tempstring1, tempstring2);
  4234.             addreactionnode(&List2, tempstring1);
  4235.             // tell number of colours to user?
  4236.  
  4237.             strcpy(tempstring1, "Masking:            ");
  4238.             if (contents[which].DataPtr[9] == 0)
  4239.             {   strcat(tempstring1, "0 (Opaque)");
  4240.             } elif (contents[which].DataPtr[9] == 1)
  4241.             {   strcat(tempstring1, "1 (Mask plane)");
  4242.             } elif (contents[which].DataPtr[9] == 2)
  4243.             {   strcat(tempstring1, "2 (Transparent colour)");
  4244.             } elif (contents[which].DataPtr[9] == 3)
  4245.             {   strcat(tempstring1, "3 (Lasso)");
  4246.             } else strcat(tempstring1, "?");
  4247.             addreactionnode(&List2, tempstring1);
  4248.  
  4249.             strcpy(tempstring1, "Compression:        ");
  4250.             if (contents[which].DataPtr[10] == 0)
  4251.             {   strcat(tempstring1, "None");
  4252.             } elif (contents[which].DataPtr[10] == 1)
  4253.             {   strcat(tempstring1, "Byte run encoding");
  4254.             } else strcat(tempstring1, "?");
  4255.             addreactionnode(&List2, tempstring1);
  4256.  
  4257.             // Next (11) is a pad byte.
  4258.  
  4259.             strcpy(tempstring1, "Transparent colour: ");
  4260.             if (contents[which].DataPtr[9] != 2
  4261.              && contents[which].DataPtr[9] != 3)
  4262.             {   strcat(tempstring1, "n/a");
  4263.             } else
  4264.             {   stcl_d(tempstring2, (256 * contents[which].DataPtr[12])
  4265.                                   +        contents[which].DataPtr[13]);
  4266.                 strcat(tempstring1, tempstring2);
  4267.             }
  4268.             addreactionnode(&List2, tempstring1);
  4269.  
  4270.             strcpy(tempstring1, "Aspect ratio:       ");
  4271.             stcl_d(tempstring2, (UBYTE) contents[which].DataPtr[14]);
  4272.             strcat(tempstring1, tempstring2);
  4273.             strcat(tempstring1, ":");
  4274.             stcl_d(tempstring2, (UBYTE) contents[which].DataPtr[15]);
  4275.             strcat(tempstring1, tempstring2);
  4276.             addreactionnode(&List2, tempstring1);
  4277.  
  4278.             strcpy(tempstring1, "Page size:          ");
  4279.             stcl_d(tempstring2, (256 * contents[which].DataPtr[16])
  4280.                               +        contents[which].DataPtr[17]); // WORD
  4281.             strcat(tempstring1, tempstring2);
  4282.             strcat(tempstring1, "x");
  4283.             stcl_d(tempstring2, (256 * contents[which].DataPtr[18])
  4284.                               +        contents[which].DataPtr[19]); // WORD
  4285.             strcat(tempstring1, tempstring2);
  4286.             addreactionnode(&List2, tempstring1);
  4287.     }   }   }
  4288.  
  4289.     if (!known || iff.raw)
  4290.     {   for (i = 0; i < contents[which].bytes; i += BYTESPERLINE)
  4291.         {   strcpy(tempstring1, "$");
  4292.  
  4293.             hexalize(i / 16777216); // do 1st byte
  4294.             j = i % 16777216;       // remove 1st byte
  4295.             hexalize(j / 65536);    // do 2nd byte
  4296.             j %= 65536;             // remove 2nd byte
  4297.             hexalize(j / 256);      // do 3rd byte
  4298.             hexalize(j % 256);      // do 4th byte
  4299.  
  4300.             strcat(tempstring1, ": ");
  4301.             for (j = 0; j < BYTESPERLINE; j++)
  4302.             {   if (contents[which].bytes > i + j)
  4303.                 {   hexalize(contents[which].DataPtr[i + j]);
  4304.                 } else
  4305.                 {   strcat(tempstring1, "##");
  4306.                 }
  4307.                 if (j % 2)
  4308.                 {   strcat(tempstring1, " ");
  4309.             }   }
  4310.             for (j = 0; j < BYTESPERLINE; j++)
  4311.             {   if (contents[which].bytes > i + j)
  4312.                 {   if (contents[which].DataPtr[i + j] < ' ') // if an unprintable character
  4313.                     {   strcat(tempstring1, ".");
  4314.                     } else
  4315.                     {   length = strlen(tempstring1);
  4316.                         tempstring1[length] = contents[which].DataPtr[i + j];
  4317.                         tempstring1[length + 1] = 0;
  4318.                 }   }
  4319.                 else
  4320.                 {   strcat(tempstring1, "#");
  4321.             }   }
  4322.             addreactionnode(&List2, tempstring1);
  4323.     }   }
  4324.     if (!known)
  4325.     {   chunkdesc("?", FALSE);
  4326.     }
  4327.  
  4328.     SetGadgetAttrs
  4329.     (   iff_gadgets[GID_6_LB2],
  4330.         MainWindowPtr, NULL,
  4331.         LISTBROWSER_Labels, &List2,
  4332.         TAG_END
  4333.     );
  4334. }
  4335.  
  4336. MODULE void chunkdesc(STRPTR desc, ABOOL isknown)
  4337. {   SetGadgetAttrs
  4338.     (   iff_gadgets[GID_6_ST4],
  4339.         MainWindowPtr, NULL,
  4340.         STRINGA_TextVal, desc,
  4341.         TAG_END
  4342.     );
  4343.     known = isknown;
  4344. }
  4345.  
  4346. MODULE void binarize(UBYTE data)
  4347. {   SLONG i; // must be signed
  4348.  
  4349.     for (i = 7; i >= 0; i--)
  4350.     {   if (data & (1 << i))
  4351.         {   strcat(tempstring1, "1");
  4352.         } else
  4353.         {   strcat(tempstring1, "0");
  4354. }   }   }
  4355.  
  4356. MODULE void hexalize(UBYTE data)
  4357. {   // Converts an unsigned byte into a hexadecimal string
  4358.  
  4359.     // do the high byte
  4360.     if (data / 16 >= 10)
  4361.     {   tempstring2[0] = (data / 16) - 10 + 'A'; // must be done in this order to prevent overflow during calculation of the value
  4362.     } else
  4363.     {   tempstring2[0] = (data / 16) + '0';
  4364.     }
  4365.  
  4366.     // now the low byte
  4367.     if (data % 16 >= 10)
  4368.     {   tempstring2[1] = (data % 16) - 10 + 'A';
  4369.     } else
  4370.     {   tempstring2[1] = (data % 16) + '0';
  4371.     }
  4372.     tempstring2[2] = 0;
  4373.     strcat(tempstring1, tempstring2);
  4374. }
  4375.  
  4376. MODULE ULONG getulong(UBYTE* start)
  4377. {   return (ULONG) ((16777216 * *(start    ))
  4378.                   + (   65536 * *(start + 1))
  4379.                   + (     256 * *(start + 2))
  4380.                   +             *(start + 3));
  4381. }
  4382. MODULE SLONG getslong(UBYTE* start)
  4383. {   return (SLONG) ((16777216 * *(start    ))
  4384.                   + (   65536 * *(start + 1))
  4385.                   + (     256 * *(start + 2))
  4386.                   +             *(start + 3));
  4387. }
  4388. MODULE ULONG getuword(UBYTE* start)
  4389. {   return (ULONG) ((     256 * *(start    ))
  4390.                   +             *(start + 1));
  4391. }
  4392. MODULE SLONG getsword(UBYTE* start)
  4393. {   return (SLONG) ((     256 * *(start    ))
  4394.                   +             *(start + 1));
  4395. }
  4396. MODULE SLONG getsbyte(UBYTE* start)
  4397. {   return (SBYTE) (*start);
  4398. }
  4399.  
  4400. MODULE void writeiffgadgets(void)
  4401. {   // update the gadgets according to variables
  4402.  
  4403.     SetGadgetAttrs
  4404.     (   iff_gadgets[GID_6_CB2], MainWindowPtr, NULL,
  4405.         GA_Selected, iff.obsolete,
  4406.     TAG_END);
  4407.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB2], MainWindowPtr, NULL);
  4408.     SetGadgetAttrs
  4409.     (   iff_gadgets[GID_6_CB3], MainWindowPtr, NULL,
  4410.         GA_Selected, iff.private,
  4411.     TAG_END);
  4412.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB3], MainWindowPtr, NULL);
  4413.     SetGadgetAttrs
  4414.     (   iff_gadgets[GID_6_CB4], MainWindowPtr, NULL,
  4415.         GA_Selected, iff.proposal,
  4416.     TAG_END);
  4417.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB4], MainWindowPtr, NULL);
  4418.     SetGadgetAttrs
  4419.     (   iff_gadgets[GID_6_CB5], MainWindowPtr, NULL,
  4420.         GA_Selected, iff.reserved,
  4421.     TAG_END);
  4422.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB5], MainWindowPtr, NULL);
  4423.     SetGadgetAttrs
  4424.     (   iff_gadgets[GID_6_CB6], MainWindowPtr, NULL,
  4425.         GA_Selected, iff.standard,
  4426.     TAG_END);
  4427.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB6], MainWindowPtr, NULL);
  4428.     SetGadgetAttrs
  4429.     (   iff_gadgets[GID_6_CB7], MainWindowPtr, NULL,
  4430.         GA_Selected, iff.unregistered,
  4431.     TAG_END);
  4432.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB7], MainWindowPtr, NULL);
  4433.     SetGadgetAttrs
  4434.     (   iff_gadgets[GID_6_CB8], MainWindowPtr, NULL,
  4435.         GA_Selected, iff.rkm,
  4436.     TAG_END);
  4437.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB8], MainWindowPtr, NULL);
  4438.     SetGadgetAttrs
  4439.     (   iff_gadgets[GID_6_CB9], MainWindowPtr, NULL,
  4440.         GA_Selected, iff.cd,
  4441.     TAG_END);
  4442.     RefreshGadgets((struct Gadget *) iff_gadgets[GID_6_CB9], MainWindowPtr, NULL);
  4443.     SetGadgetAttrs
  4444.     (   iff_gadgets[GID_6_ST1],
  4445.         MainWindowPtr, NULL,
  4446.         STRINGA_TextVal, queryform,
  4447.         TAG_END
  4448.     );
  4449.     chunkdesc("-", FALSE);
  4450. }
  4451.  
  4452. MODULE void dotextattr(UBYTE* offset)
  4453. {   ULONG uvalue;
  4454.  
  4455.     // handles TextAttr structure (8 bytes)
  4456.     // name pointer is ignored
  4457.  
  4458.             strcpy(tempstring1, " Height:                ");
  4459.             uvalue = getuword(offset + 4);
  4460.             stcl_d(tempstring2, uvalue);
  4461.             strcat(tempstring1, tempstring2);
  4462.             addreactionnode(&List2, tempstring1);
  4463.  
  4464.             addreactionnode(&List2, " Style:");
  4465.  
  4466.             strcpy(tempstring1, "  Underlined?           ");
  4467.             if ((*(offset + 6)) &   1) // FSF_UNDERLINED
  4468.             {   strcat(tempstring1, "Yes");
  4469.             } else
  4470.             {   strcat(tempstring1, "No");
  4471.             }
  4472.             addreactionnode(&List2, tempstring1);
  4473.  
  4474.             strcpy(tempstring1, "  Bold?                 ");
  4475.             if (*(offset + 6) &   2) // FSF_BOLD
  4476.             {   strcat(tempstring1, "Yes");
  4477.             } else
  4478.             {   strcat(tempstring1, "No");
  4479.             }
  4480.             addreactionnode(&List2, tempstring1);
  4481.  
  4482.             strcpy(tempstring1, "  Italic?               ");
  4483.             if (*(offset + 6) &   4) // FSF_UNDERLINED
  4484.             {   strcat(tempstring1, "Yes");
  4485.             } else
  4486.             {   strcat(tempstring1, "No");
  4487.             }
  4488.             addreactionnode(&List2, tempstring1);
  4489.  
  4490.             strcpy(tempstring1, "  Extended?             ");
  4491.             if (*(offset + 6) &   8) // FSF_EXTENDED
  4492.             {   strcat(tempstring1, "Yes");
  4493.             } else
  4494.             {   strcat(tempstring1, "No");
  4495.             }
  4496.             addreactionnode(&List2, tempstring1);
  4497.  
  4498.             strcpy(tempstring1, "  Colour font?          ");
  4499.             if (*(offset + 6) &  64) // FSF_COLORFONT
  4500.             {   strcat(tempstring1, "Yes");
  4501.             } else
  4502.             {   strcat(tempstring1, "No");
  4503.             }
  4504.             addreactionnode(&List2, tempstring1);
  4505.  
  4506.             strcpy(tempstring1, "  Tagged?               ");
  4507.             if (*(offset + 6) & 128) // FSF_TAGGED
  4508.             {   strcat(tempstring1, "Yes");
  4509.             } else
  4510.             {   strcat(tempstring1, "No");
  4511.             }
  4512.             addreactionnode(&List2, tempstring1);
  4513.  
  4514.             addreactionnode(&List2, " Flags:");
  4515.  
  4516.             strcpy(tempstring1, "  ROM font?             ");
  4517.             if (*(offset + 7) &   1) // FPF_ROMFONT
  4518.             {   strcat(tempstring1, "Yes");
  4519.             } else
  4520.             {   strcat(tempstring1, "No");
  4521.             }
  4522.             addreactionnode(&List2, tempstring1);
  4523.  
  4524.             strcpy(tempstring1, "  Disk font?            ");
  4525.             if (*(offset + 7) &   2) // FPF_DISKFONT
  4526.             {   strcat(tempstring1, "Yes");
  4527.             } else
  4528.             {   strcat(tempstring1, "No");
  4529.             }
  4530.             addreactionnode(&List2, tempstring1);
  4531.  
  4532.             strcpy(tempstring1, "  Reversed?             ");
  4533.             if (*(offset + 7) &   4) // FPF_REVPATH
  4534.             {   strcat(tempstring1, "Yes");
  4535.             } else
  4536.             {   strcat(tempstring1, "No");
  4537.             }
  4538.             addreactionnode(&List2, tempstring1);
  4539.  
  4540.             strcpy(tempstring1, "  HiRes non-interlaced? ");
  4541.             if (*(offset + 7) &   8) // FPF_TALLDOT
  4542.             {   strcat(tempstring1, "Yes");
  4543.             } else
  4544.             {   strcat(tempstring1, "No");
  4545.             }
  4546.             addreactionnode(&List2, tempstring1);
  4547.  
  4548.     strcpy(tempstring1, "  LoRes interlaced?     ");
  4549.     if (*(offset + 7) &  16) // FPF_WIDEDOT
  4550.     {   strcat(tempstring1, "Yes");
  4551.     } else
  4552.     {   strcat(tempstring1, "No");
  4553.     }
  4554.     addreactionnode(&List2, tempstring1);
  4555.  
  4556.     strcpy(tempstring1, "  Proportional?         ");
  4557.     if (*(offset + 7) &  32) // FPF_PROPORTIONAL
  4558.     {   strcat(tempstring1, "Yes");
  4559.     } else
  4560.     {   strcat(tempstring1, "No");
  4561.     }
  4562.     addreactionnode(&List2, tempstring1);
  4563.  
  4564.     strcpy(tempstring1, "  Designed?             ");
  4565.     if (*(offset + 7) &  64) // FPF_DESIGNED
  4566.     {   strcat(tempstring1, "Yes");
  4567.     } else
  4568.     {   strcat(tempstring1, "No");
  4569.     }
  4570.     addreactionnode(&List2, tempstring1);
  4571.  
  4572.     strcpy(tempstring1, "  Removed?              ");
  4573.     if (*(offset + 7) & 128) // FPF_REMOVED
  4574.     {   strcat(tempstring1, "Yes!");
  4575.     } else
  4576.     {   strcat(tempstring1, "No");
  4577.     }
  4578.     addreactionnode(&List2, tempstring1);
  4579. }
  4580.  
  4581. MODULE void docountry(UBYTE* offset)
  4582. {   ULONG uvalue;
  4583.  
  4584.     // handles CountryPrefs structure (8 bytes)
  4585.  
  4586.     // 16 reserved bytes at start
  4587.  
  4588.     strcpy(tempstring1, "Country code:           ");
  4589.     uvalue = getulong(offset + 16); // ULONG
  4590.     stcl_d(tempstring2, uvalue);
  4591.     strcat(tempstring1, tempstring2);
  4592.     addreactionnode(&List2, tempstring1);
  4593.  
  4594.     strcpy(tempstring1, "Telephone code:         ");
  4595.     uvalue = getulong(offset + 20); // ULONG
  4596.     stcl_d(tempstring2, uvalue);
  4597.     strcat(tempstring1, tempstring2);
  4598.     addreactionnode(&List2, tempstring1);
  4599.  
  4600.     strcpy(tempstring1, "Measuring system:       ");
  4601.     if (*(offset + 24) == 0) // MS_ISO
  4602.     {   strcat(tempstring1, "0 (Metric)");
  4603.     } elif (*(offset + 24) == 1) // MS_AMERICAN
  4604.     {   strcat(tempstring1, "1 (American)");
  4605.     } elif (*(offset + 24) == 2) // MS_IMPERIAL
  4606.     {   strcat(tempstring1, "2 (Imperial)");
  4607.     } elif (*(offset + 24) == 3) // MS_BRITISH
  4608.     {   strcat(tempstring1, "3 (British)");
  4609.     } else
  4610.     {   strcat(tempstring1, "?");
  4611.     }
  4612.     addreactionnode(&List2, tempstring1);
  4613.  
  4614.     strcpy(tempstring1, "Long date/time format:  ");
  4615.     strcat(tempstring1, offset + 25); // 80 chars
  4616.     addreactionnode(&List2, tempstring1);
  4617.  
  4618.     strcpy(tempstring1, "Long date format:       ");
  4619.     strcat(tempstring1, offset + 105); // 40 chars
  4620.     addreactionnode(&List2, tempstring1);
  4621.  
  4622.     strcpy(tempstring1, "Long time format:       ");
  4623.     strcat(tempstring1, offset + 145); // 40 chars
  4624.     addreactionnode(&List2, tempstring1);
  4625.  
  4626.     strcpy(tempstring1, "Short date/time format: ");
  4627.     strcat(tempstring1, offset + 185); // 80 chars
  4628.     addreactionnode(&List2, tempstring1);
  4629.  
  4630.     strcpy(tempstring1, "Short date format:      ");
  4631.     strcat(tempstring1, offset + 265); // 40 chars
  4632.     addreactionnode(&List2, tempstring1);
  4633.  
  4634.     strcpy(tempstring1, "Short time format:      ");
  4635.     strcat(tempstring1, offset + 305); // 40 chars
  4636.     addreactionnode(&List2, tempstring1);
  4637.  
  4638.     addreactionnode(&List2, "Numeric values:");
  4639.  
  4640.     strcpy(tempstring1, " Decimal point:         ");
  4641.     strcat(tempstring1, offset + 345); // 10 chars
  4642.     addreactionnode(&List2, tempstring1);
  4643.  
  4644.     strcpy(tempstring1, " Intgr group separator: ");
  4645.     strcat(tempstring1, offset + 355); // 10 chars
  4646.     addreactionnode(&List2, tempstring1);
  4647.  
  4648.     strcpy(tempstring1, " Frac. group separator: ");
  4649.     strcat(tempstring1, offset + 365); // 10 chars
  4650.     addreactionnode(&List2, tempstring1);
  4651.  
  4652.     /* Integer group size (10 chars) and
  4653.        Fractional group size (10 chars): not strings (currently skipped */
  4654.  
  4655.     addreactionnode(&List2, "General monetary values:");
  4656.  
  4657.     strcpy(tempstring1, " Decimal point:         ");
  4658.     strcat(tempstring1, offset + 395); // 10 chars
  4659.     addreactionnode(&List2, tempstring1);
  4660.  
  4661.     strcpy(tempstring1, " Intgr group separator: ");
  4662.     strcat(tempstring1, offset + 405); // 10 chars
  4663.     addreactionnode(&List2, tempstring1);
  4664.  
  4665.     strcpy(tempstring1, " Frac. group separator: ");
  4666.     strcat(tempstring1, offset + 415); // 10 chars
  4667.     addreactionnode(&List2, tempstring1);
  4668.  
  4669.     /* Integer group size (10 chars) and
  4670.        Fractional group size (10 chars): not strings (currently skipped) */
  4671.  
  4672.     addreactionnode(&List2, " Digits after decimal point:");
  4673.  
  4674.     strcpy(tempstring1, "  Intranational:        ");
  4675.     stcl_d(tempstring2, (ULONG) ((UBYTE) *(offset + 445)));
  4676.     strcat(tempstring1, tempstring2);
  4677.     addreactionnode(&List2, tempstring1);
  4678.     strcpy(tempstring1, "  International:        ");
  4679.     stcl_d(tempstring2, (ULONG) ((UBYTE) *(offset + 446)));
  4680.     strcat(tempstring1, tempstring2);
  4681.     addreactionnode(&List2, tempstring1);
  4682.  
  4683.     addreactionnode(&List2, "Currency symbols:");
  4684.  
  4685.     strcpy(tempstring1, " Large amounts symbol:  ");
  4686.     strcat(tempstring1, offset + 447); // 10 chars
  4687.     addreactionnode(&List2, tempstring1);
  4688.  
  4689.     strcpy(tempstring1, " Small amounts symbol:  ");
  4690.     strcat(tempstring1, offset + 457); // 10 chars
  4691.     addreactionnode(&List2, tempstring1);
  4692.  
  4693.     strcpy(tempstring1, " ISO 4217 code:         ");
  4694.     strcat(tempstring1, offset + 467); // 10 chars
  4695.     addreactionnode(&List2, tempstring1);
  4696.  
  4697.     addreactionnode(&List2, "Positive monetary values:");
  4698.  
  4699.     strcpy(tempstring1, " Positive sign:         ");
  4700.     strcat(tempstring1, offset + 477); // 10 chars
  4701.     addreactionnode(&List2, tempstring1);
  4702.  
  4703.     strcpy(tempstring1, " Space next to sign?    ");
  4704.     if (*(offset + 487) == 0) // SS_NOSPACE
  4705.     {   strcat(tempstring1, "No");
  4706.     } elif (*(offset + 487) == 1) // SS_SPACE
  4707.     {   strcat(tempstring1, "Yes");
  4708.     } else strcat(tempstring1, "?");
  4709.     addreactionnode(&List2, tempstring1);
  4710.  
  4711.     strcpy(tempstring1, " Positive sign pos.:    ");
  4712.     if (*(offset + 488) == 0) // SP_PARENS
  4713.     {   strcat(tempstring1, "0 (parentheses around amount and symbol)");
  4714.     } elif (*(offset + 488) == 1) // SP_PREC_ALL
  4715.     {   strcat(tempstring1, "1 (sign is before amount and symbol)");
  4716.     } elif (*(offset + 488) == 2) // SP_SUCC_ALL
  4717.     {   strcat(tempstring1, "2 (sign is after amount and symbol)");
  4718.     } elif (*(offset + 488) == 3) // SP_PREC_CURR
  4719.     {   strcat(tempstring1, "3 (sign is before symbol)");
  4720.     } elif (*(offset + 488) == 4) // SP_SUCC_CURR
  4721.     {   strcat(tempstring1, "4 (sign is after symbol)");
  4722.     } else
  4723.     {   strcat(tempstring1, "?");
  4724.     }
  4725.     addreactionnode(&List2, tempstring1);
  4726.  
  4727.     strcpy(tempstring1, " Currency symbol pos.:  ");
  4728.     if (*(offset + 489) == 0) // CSP_PRECEDES
  4729.     {   strcat(tempstring1, "0 (symbol is before amount)");
  4730.     } elif (*(offset + 489) == 1) // CSP_SUCCEEDS
  4731.     {   strcat(tempstring1, "1 (symbol is after amount)");
  4732.     } else
  4733.     {   strcat(tempstring1, "?");
  4734.     }
  4735.     addreactionnode(&List2, tempstring1);
  4736.  
  4737.     addreactionnode(&List2, "Negative monetary values:");
  4738.  
  4739.     strcpy(tempstring1, " Negative sign:         ");
  4740.     strcat(tempstring1, offset + 500); // 10 chars
  4741.     addreactionnode(&List2, tempstring1);
  4742.  
  4743.     strcpy(tempstring1, " Space next to sign?    ");
  4744.     if (*(offset + 500) == 0) // SS_NOSPACE
  4745.     {   strcat(tempstring1, "No");
  4746.     } elif (*(offset + 500) == 1) // SS_SPACE
  4747.     {   strcat(tempstring1, "Yes");
  4748.     } else strcat(tempstring1, "?");
  4749.     addreactionnode(&List2, tempstring1);
  4750.  
  4751.     strcpy(tempstring1, " Negative sign pos.:    ");
  4752.     if (*(offset + 501) == 0) // SP_PARENS
  4753.     {   strcat(tempstring1, "0 (parentheses around amount and symbol)");
  4754.     } elif (*(offset + 501) == 1) // SP_PREC_ALL
  4755.     {   strcat(tempstring1, "1 (sign is before amount and symbol)");
  4756.     } elif (*(offset + 501) == 2) // SP_SUCC_ALL
  4757.     {   strcat(tempstring1, "2 (sign is after amount and symbol)");
  4758.     } elif (*(offset + 501) == 3) // SP_PREC_CURR
  4759.     {   strcat(tempstring1, "3 (sign is before symbol)");
  4760.     } elif (*(offset + 501) == 4) // SP_SUCC_CURR
  4761.     {   strcat(tempstring1, "4 (sign is after symbol)");
  4762.     } else
  4763.     {   strcat(tempstring1, "?");
  4764.     }
  4765.     addreactionnode(&List2, tempstring1);
  4766.  
  4767.     strcpy(tempstring1, " Currency symbol pos.:  ");
  4768.     if (*(offset + 502) == 0) // CSP_PRECEDES
  4769.     {   strcat(tempstring1, "0 (symbol is before amount)");
  4770.     } elif (*(offset + 502) == 1) // CSP_SUCCEEDS
  4771.     {   strcat(tempstring1, "1 (symbol is after amount)");
  4772.     } else
  4773.     {   strcat(tempstring1, "?");
  4774.     }
  4775.     addreactionnode(&List2, tempstring1);
  4776.  
  4777.     strcpy(tempstring1, "First day of the week:  ");
  4778.     if (*(offset + 503) == 0)
  4779.     {   strcat(tempstring1, "0 (Sunday)");
  4780.     } elif (*(offset + 503) == 1)
  4781.     {   strcat(tempstring1, "1 (Monday)");
  4782.     } elif (*(offset + 503) == 2)
  4783.     {   strcat(tempstring1, "2 (Tuesday)");
  4784.     } elif (*(offset + 503) == 3)
  4785.     {   strcat(tempstring1, "3 (Wednesday)");
  4786.     } elif (*(offset + 503) == 4)
  4787.     {   strcat(tempstring1, "4 (Thursday)");
  4788.     } elif (*(offset + 503) == 5)
  4789.     {   strcat(tempstring1, "5 (Friday)");
  4790.     } elif (*(offset + 503) == 6)
  4791.     {   strcat(tempstring1, "6 (Saturday)");
  4792.     } else
  4793.     {   strcat(tempstring1, "?");
  4794.     }
  4795.     addreactionnode(&List2, tempstring1);
  4796. }
  4797.  
  4798. AGLOBAL void iff_init(void)
  4799. {   iff.raw = FALSE;
  4800.  
  4801.     NewList(&List1);
  4802.     NewList(&List2);
  4803. }
  4804.  
  4805. AGLOBAL void iff_die(void)
  4806. {   IOBuffer[19] = (UBYTE) iff.raw;
  4807. }
  4808.  
  4809. AGLOBAL void iff_config(void)
  4810. {   iff.raw = (ULONG) IOBuffer[19];
  4811. }
  4812.  
  4813. AGLOBAL ULONG Hook6Func(struct Hook *h, VOID *o, VOID *msg)
  4814. {   /* "When the hook is called, the data argument points to the 
  4815.     window object and message argument to the IntuiMessage." */
  4816.  
  4817.     UWORD code, qual;
  4818.     ULONG scroll = 0;
  4819.  
  4820.     geta4(); // wait till here before doing anything
  4821.  
  4822.     code = ((struct IntuiMessage *) msg)->Code;
  4823.     qual = ((struct IntuiMessage *) msg)->Qualifier;
  4824.  
  4825.     switch(code)
  4826.     {
  4827.     case SCAN_HELP:
  4828.         helpabout();
  4829.     break;
  4830.     case SCAN_ESCAPE:
  4831.         if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  4832.         {   cleanexit(EXIT_SUCCESS);
  4833.         } else page = 0;
  4834.     break;
  4835.     case SCAN_UP:
  4836.         if (qual & IEQUALIFIER_CONTROL)
  4837.         {   scroll = LBP_TOP;
  4838.         } elif (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
  4839.         {   scroll = LBP_PAGEUP;
  4840.         } else scroll = LBP_LINEUP;
  4841.     break;
  4842.     case SCAN_DOWN:
  4843.         if (qual & IEQUALIFIER_CONTROL)
  4844.         {   scroll = LBP_BOTTOM;
  4845.         } elif (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
  4846.         {   scroll = LBP_PAGEDOWN;
  4847.         } else scroll = LBP_LINEDOWN;
  4848.     break;
  4849.     case SCAN_PERIOD:
  4850.         if (asl("~(#?.info)"))
  4851.         {   strcpy(iff.pathname, aslresult);
  4852.  
  4853.             SetGadgetAttrs
  4854.             (   iff_gadgets[GID_6_ST6], MainWindowPtr, NULL,
  4855.                 STRINGA_TextVal, iff.pathname,
  4856.                 TAG_END
  4857.             ); // we don't know how many files in advance...
  4858.  
  4859.             readiff();
  4860.         }
  4861.     break;
  4862.     case SCAN_F:
  4863.         ActivateLayoutGadget(iff_gadgets[GID_6_LY1], MainWindowPtr, NULL, (Object) iff_gadgets[GID_6_ST1]);
  4864.     break;
  4865.     case SCAN_P:
  4866.         ActivateLayoutGadget(iff_gadgets[GID_6_LY1], MainWindowPtr, NULL, (Object) iff_gadgets[GID_6_ST6]);
  4867.     break;
  4868.     case SCAN_R:
  4869.         // the gadget is handled automatically by the system, all we need
  4870.         // to do is update our internal record of the state of the gadget
  4871.         if (!(GetAttr
  4872.         (   GA_Selected, iff_gadgets[GID_6_CB1], (ULONG *) &iff.raw
  4873.         )))
  4874.         {   rq("Unsupported inquiry!"); // should never happen
  4875.         }
  4876.         if (selectedchunk && known)
  4877.         {   tellchunk(selectedchunk);
  4878.         }
  4879.     break;
  4880.     default:
  4881.     break;
  4882.     }
  4883.  
  4884.     if (code == SCAN_UP || code == SCAN_DOWN)
  4885.     {   SetGadgetAttrs
  4886.         (   iff_gadgets[GID_6_LB2],       // pointer to gadget
  4887.             MainWindowPtr,                // pointer to window (not window object!)
  4888.             NULL,                         // pointer to requester
  4889.             LISTBROWSER_Position, scroll, // tags
  4890.             TAG_DONE                      // done
  4891.         );
  4892.     }
  4893.  
  4894.     return(1);
  4895. }
  4896.